Spring Data概述
- SpringDate:Spring的一个子项目.用于简化数据库访问,支持NoSQL和关系型数据库.其主要目标是使数据库的访问变得方便快捷.
- SpringDate项目支持NoSQL存储:
- MongoDB(文档数据库)
- Neo4j(图形数据库)
- Redis(键/值数据库)
- Hbase(列族数据库)
- SpringDate项目支持的关系型存储技术:
- JDBC
- JPA
JPA Spring Data概述
- JPA Spring Data:致力于减少数据访问层(DAO)的开发量.开发者唯一要做的,就只是声明持久层的接口,其他都交给Spring Data JPA来做.
- 框架是怎么代替开发者实现业务逻辑的?比如:当有一个UserDao.findUserById()这样一个方法声明,大致应该能判断出这事根据定条件ID查询出满足条件的User对象.Spring Data JPA做的便是规范方法的名字,根据符合规范的名字来确定方法需要实现声明样的逻辑
使用Spring Data JPA进行持久层开发的四个步骤:
- 配置Spring整合JPA
- 在Spring配置文件中配置SpringData,让Spring为声明的接口创建代理对象.配置了jpa:repositories后,Spring初始化容器时将会扫描base-package指定的包目录及子目录,为继承Repository或其子接口的接口创建代理对象,并将代理对象注册为SpringBean,业务层便可以通过Spring自动封装的特性来直接使用该对象.
- 声明持久层的接口,该接口继承Repository,Repository是一个标记型接口,它不包含任何方法,如必要,Spring Data可实现Repository其他子接口,其中定义了一些常用的增删改查,以及分页相关的方法.
- 在接口中声明需要的方法.Spring Data将根据给定的策略来为其生成实现代码
环境搭建
- 1.引入相应jar包
- 2.创建springdata的配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
<!-- 1.配置数据源 -->
<context:property-placeholder location="classpath:db.properties"/>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="${jdbc.user}"></property>
<property name="password" value="${jdbc.password}"></property>
<property name="driverClass" value="${jdbc.driverClass}"></property>
<property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
</bean>
<!-- 2.配置JPA的EntityMangerFactory -->
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"></bean>
</property>
<!--指定包扫描-->
<property name="packagesToScan" value="com.springdata.test"></property>
<property name="jpaProperties">
<props>
<!-- 二级缓存相关 -->
<!--
<prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop>
<prop key="net.sf.ehcache.configurationResourceName">ehcache-hibernate.xml</prop>
-->
<!-- 生成的数据表的列的映射策略 -->
<prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop>
<!-- hibernate 基本属性 -->
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
</bean>
<!-- 3.配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"></property>
</bean>
<!-- 4.配置支持注解的事务 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
<!-- 5.配置SpringData -->
<!-- 加入 jpa 的命名空间 -->
<!-- base-package:扫描Repository Bean 所在的 package -->
<jpa:repositories base-package="com.springdata.test"
entity-manager-factory-ref="entityManagerFactory"></jpa:repositories>
</beans>
- 3.数据库里对外连接
jdbc.user=root
jdbc.password=root
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.jdbcUrl=jdbc:mysql://localhost:3306/jpa
- 4.新建junit测试类,测试是否成功连接数据库
class SpringDataTest {
private ApplicationContext ctx = null;
{
ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
}
@Test
void testDataSource() throws SQLException {
DataSource dataSource = ctx.getBean(DataSource.class);
System.out.println(dataSource.getConnection());
}
}
连接成功打印出连接信息

测试JPA
用JPA的EntityMangerFactory代码生成表
- 1.新建一个实体类,定义属性,生成get/set,toString方法
- 在实力类上加注解@Etity和@Table(name="JPA_PERSONS") //意思是在数据库中建表,name就是表名
- 在属性id上面加上@GeneratedValue和@Id注解
@Entity
@Table(name="JPA_PERSONS")
public class Person {
private Integer id;
private String lastName;
private String email;
private Date birth;
@GeneratedValue
@Id
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
只截取了一部分
- 2.在测试类中生成数据库表(里面不用写任何代码)
- 测试类启动就会创建ApplicationContext对象,然后会生成上面配置文件的entityManagerFactory,通过entityManagerFactory生成数据库表(springdata配置文件的第二条)
@Test
public void testJpa() {
}
启动无报错后就会在数据库中生成一个表(数据是后加的)

SpringData-Repository接口
- 1.在数据库添加一条测试数据
- 2.新建一个持久层映射类(继承Repository接口,也可以使用注解)
- @RepositoryDefinition注解要声明domainClass和idClass属性
- 类中写查询方法
/**
* 1.Repository是一个空接口,即是一个标记接口
* 2.若我们定义的接口继承了Repository,则该接口会被IOC容器识别为一个Repository Bean.
* 纳入到IOC容器中,进而可以在该接口中定义满足一定规范的方法.
* 3.实际上,也可以通过@RepositoryDefinition 注解来替代继承Repository 接口
*
*/
//传入的两个泛型:1.要处理的实体类的类型2.主键的类型
@RepositoryDefinition(domainClass=Person.class,idClass=Integer.class)
public interface PersonRepsotory{
//根据lastName 来获取对应的Person
Person getByLastName(String lastName);
}
- 3.在测试类中进行测试
- 通过上下文得到持久层对象,在通过持久层调用查询方法查出表中数据
- 参数是根据别名查询,所以参数是数据库中数据"tom"
@Test
public void testGet() {
PersonRepsotory personRepsotory = ctx.getBean(PersonRepsotory.class);
Person person = personRepsotory.getByLastName("tom");
System.out.println(person);
}
查询结果


条件查询

- 在持久层类中写查询方法
//WHERE lastName LIKE ?% AND id < ?(以一个模糊做开始和id小于的条件做查询)
List<Person> getByLastNameStartingWithAndIdLessThan(String lastName,Integer id);
//WHERE lastName LIKE %? AND id < ?(以一个模糊做结束和id小于的条件做查询)
List<Person> getByLastNameEndingWithAndIdLessThan(String lastName,Integer id);
测试类调用
/*
* 条件查询的方法:以某字符开头并且id小于?的方法
*/
@Test
public void testKeyWords() {
List<Person> person = personRepsotory.getByLastNameStartingWithAndIdLessThan("c", 6);
System.out.println(person);
//(以一个模糊做结束和id小于的条件做查询)方法
List<Person> person1 = personRepsotory.getByLastNameEndingWithAndIdLessThan("c", 6);
System.out.println(person1);
}
@Query注解
- 一些根据关键字无法实现的查询可以通过@Query注解来实现
//查询id值最大的那个Person对象
//使用@Query 注解可以自定义 JPQL 语句以实现灵活的查询
@Query("SELECT p FROM Person p WHERE p.id = (SELECT max(p2.id) FROM Person p2)")
Person getMaxIdPerson();
- 传递参数的两种方式
// 为@Query 注解传递参数的方式1:使用占位符.这种方式参数顺序必须一致
@Query("SELECT p FROM Person p WHERE p.lastName = ? AND p.email = ?")
List<Person> testQueryAnnotationParms1(String lastName, String email);
// @Query注解传递参数方式2:命名参数的方式,对参数名字进行绑定,可以不按顺序
@Query("SELECT p FROM Person p WHERE p.lastName = :lastName AND p.email = :email")
List<Person> testQueryAnnotationParms2(@Param("email") String email, @Param("lastName") String lastName);