快速入门spring-data-jpa,接口方法详解

来源:互联网 发布:如何更改数据库所有者 编辑:程序博客网 时间:2024/05/16 09:48
一.spring-data简介

1.概括:

      spring家族中的一员,用来简化构建基于 Spring 框架应用的数据访问,包括关系型数据库,非关系型数据库、Map-Reduce 框架、云数据服务等等的访问支持


2.主要子项目:
Spring Data Commons----------------Core Spring概念支持每个Spring Data项目
Spring Data Gemfire------------------提供从Spring应用程序轻松配置和访问GemFire
Spring Data JPA-----------------------使其易于实现基于JPA的存储库(JPA 简化 DAO 的编写)
Spring Data KeyValue-----------------基于映射的存储库和SPI,可轻松构建一个用于键值存储的Spring数据模块
Spring Data LDAP---------------------为Spring LDAP提供Spring数据存储库支持
spring Data MogoDB-----------------MongoDB是基于Spring的对象文档支持和存储库
Spring Data REST----------------------将Spring数据存储库导出为超媒体驱动的RESTful资源
Spring Data Redis---------------------提供从Spring应用程序轻松配置和访问Redis
Spring Data for Apache Cassandra---Apache Cassandra的Spring数据模块
Spring Data Apache Solr--------------Apache Solr的Spring数据模块

上面是我对官网英语的小部分翻译,了解更多可以进入下面的官网地址查看
网址:http://projects.spring.io/spring-data-jpa/
其实spring data就是为我们提供一种编码格式,规范我们的API

3.所属jar包:
spring-data-commons:一套标准API
          包括:Repository,CrudRepository,PagingAndSortingRespsitory
spring-data-jpa:基于整合JPA的实现
          包括:JpaRepository,JpaSpecificationExcutor

二.使用spring-data-jpa的环境配置


1.maven坐标:

其他maven坐标没有写出,只写出了整合jpa需要的坐标

<!-- spring data jpa 数据库持久层 --><dependency><groupId>org.springframework.data</groupId><artifactId>spring-data-jpa</artifactId><version>1.9.0.RELEASE</version></dependency>

2.applicationContext-dataSource.xml配置:

<?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:aop="http://www.springframework.org/schema/aop"xmlns:context="http://www.springframework.org/schema/context"xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:tx="http://www.springframework.org/schema/tx"xmlns:jpa="http://www.springframework.org/schema/data/jpa" xmlns:task="http://www.springframework.org/schema/task"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsdhttp://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsdhttp://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd"> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="driverClass" value="${jdbc.driver}" /><property name="jdbcUrl" value="${jdbc.url}" /> <property name="user" value="${jdbc.user}" /><property name="password" value="${jdbc.password}" /></bean><!-- 整合JPA配置 --><bean id="entityManagerFactory"class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"><property name="dataSource" ref="dataSource" /><property name="packagesToScan" value="com.yl.website.pojo" /><property name="persistenceProvider"><bean class="org.hibernate.jpa.HibernatePersistenceProvider" /></property><property name="jpaVendorAdapter"><bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"><property name="generateDdl" value="true" /><property name="database" value="MYSQL" /><property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" /><property name="showSql" value="true" /></bean></property><property name="jpaDialect"><bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" /></property><property name="jpaPropertyMap"><map><entry key="hibernate.query.substitutions" value="true 1, false 0" /><entry key="hibernate.default_batch_fetch_size" value="16" /><entry key="hibernate.max_fetch_depth" value="2" /><entry key="hibernate.generate_statistics" value="true" /><entry key="hibernate.bytecode.use_reflection_optimizer" value="true" /><entry key="hibernate.cache.use_second_level_cache" value="false" /><entry key="hibernate.cache.use_query_cache" value="false" /></map></property></bean><!-- JPA事务管理器  --><bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"><property name="entityManagerFactory" ref="entityManagerFactory" /></bean><!-- 注解管理事务 --><tx:annotation-driven transaction-manager="transactionManager"/><!-- 整合spring data jpa --><jpa:repositories base-package="com.yl.website.dao" /></beans>

3.applicationContext.xml配置:

<?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:aop="http://www.springframework.org/schema/aop"xmlns:context="http://www.springframework.org/schema/context"xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:tx="http://www.springframework.org/schema/tx"xmlns:jpa="http://www.springframework.org/schema/data/jpa" xmlns:task="http://www.springframework.org/schema/task"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsdhttp://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsdhttp://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd"> <!-- 扫描 @Server @Controller @Repository --><context:component-scan base-package="com.yl"/><!-- 加载properties文件 --><context:property-placeholder location="classpath:config.properties" /><!-- 引入外部数据文件 --><import resource="applicationContext-dataSource.xml"/></beans>

4.config.properties配置:

jdbc.url = jdbc:mysql://localhost:3306/yl_webjdbc.driver= com.mysql.jdbc.Driverjdbc.user = rootjdbc.password = root

三.Repository接口详解


Repository接口的继承体系结构:


1.Repository:空接口,标记接口(没有包含方法声明的接口)
1)Repository接口是Spring Data的核心接口,不提供任何方法
      不需要对 DAO 接口做任何实现, 实际上 spring 会调用 SimpleJpaRepository 实现
2)T是实体类的名字,ID是实体类中的ID的类型:

public interface Repository<T, ID extends Serializable> {}

      只要继承这个接口,spring就会把该接口纳入spring去管理

3)如果不继承就会报错,但是可以使用@RepositoryDefinition(domainClass = 实体类.class,idClass = 实体类中

     id的类型.class)可以代替继承

4)Repository查询方法遵循命名规则(自动生成查询语句):


举例:

public interface StudentRepotory  extends Repository<Student,Integer>{          //where name = ?      Student findByName(String name);    //Where name like ?%      List<Student> findByNameLike(String name)                  //Where lastName like ?% and id<?      List<Student> getByLastNameEndingWithAndIdLessThan(String lastName,Integer id);            //where username = ? and password = ?      Student findByUsernameAndPassword(String username,String password);       }

5)Repository查询方法不遵循命名规则(配置@Query绑定JAPL语句或者SQL语句查询):

   只需要把@Query定义在Repository中的方法名之上

public interface StudentRepotory  extends Repository<Student,Integer>{      @Query("select o from Student o where o.name=?1 and 0.age=?2")List<Student> queryStudent1(String name,Integer age);@Query("select o from Student o where o.name=:name and 0.age=:age")List<Student> queryStudent2(@Param("name")String name,@Param("age")Integer age);    @Query("select o from Student o where o.name like %?1%")List<Student> queryStudentLike1(String name);    @Query("select o from Student o where o.name like %:name%")List<Student> queryStudentLike2(@Param("name")String name); @Query("select o from Student o where id=(select min(id) from Stduent t1)")Student getStudentMinId();//nativeQuery为false配置的是JPQL,为true配置的是SQL@Query(nativeQuery = true ,value = "select count(1) from student")long getCount1();@Query(nativeQuery = false ,value = "from Student where name =?")List<Student> queryName(String name);}

6)Repository查询方法不遵循命名规则(配置@Query 没写语句 ):

    配置@Query定义在Repository中的方法名之上,实体类 上@NamedQuery 定义

//Dao层:@Querypublic List<Student> queryName(String name);//实体类:@NameQueries({@NamedQuery(name="Student.queryName",query="from Student where name=?")})public class Student{实体类对象}

7)Repository带有条件的修改和删除操作:

   使用@Query 注解 , 搭配使用@Modifying 标记是修改、删除操作

//将id为?1的最大长度改为?2@Query(value="update Standard set maxLength=?2 where id =?1")@Modifyingpublic List<Student> updateMaxLength(Integer id,Tnteger maxLength);

2. CrudRepository:继承Repository接口,实现了基本增删改查的方法
1)常用方法:
                save(entity),save(entities):保存一个实体对象或多个实体对象
                findOne(id):根据id找到一个实体对象
                exists(id):根据id判断一个实体对象是否存在
                findAll():找到所有的实体对象
                delete(id),delete(entity),delete(entities),deleteAll():根据id,一个实体对象,很多实体对象来删除实体,或者删除全部的实体

2)通过save方法来举例,其他方法的使用方法类似:

//Dao层:public interface SidebarRepository extends CrudRepository<StudentsInf, Integer> {}//Service接口:public interface SidebarService {void save(StudentsInf studentsInf);}//Service实现类:@Service@Transactionalpublic class SidebarServiceImpl implements SidebarService {@Autowiredprivate SidebarRepository sidebarRepository;@Overridepublic void save(StudentsInf studentsInf) {sidebarRepository.save(studentsInf);}}//controller层:@Controllerpublic class SidebarController {@Autowiredprivate SidebarService sidebarService;@RequestMapping("/studentSave")public String save(StudentsInf studentsInf) {sidebarService.save(studentsInf);return "studentSave"}}

3.PagingAndSortingRespsitory:继承了CrudRepository接口,实现了分页排序的方法

       带排序的查询:findAll(Sort sort)
                           (查询全部,并传入排序的字段Sort)
       带排序的分页查询:findAll(Pageable pageable)
                            (需要分页,就必须传入一个可以分页的对象Pageable)

分页举例:

//Contorller层@Controllerpublic class TeacherController {@Autowiredprivate TeacherService teacherService;@RequestMapping("/teacherShow")public String studentIntroduce(Integer page,Integer size){Page<Teacher> teacherPage = teacherService.getTeacherList(page,size);System.out.println("总页数:"+teacherPage.getTotalPages());System.out.println("总记录数:"+teacherPage.getTotalElements());System.out.println("当前第几页:"+(teacherPage.getNumber()+1));System.out.println("当前页面的集合"+teacherPage.getContent());System.out.println("当前页面的记录数"+teacherPage.getNumberOfElements());return "teacherShow";}}//Service层public interface TeacherService {Page<Teacher> getTeacherList(Integer page,Integer size);}//ServiceImp层@Service@Transactionalpublic class TeacherServiceImpl implements TeacherService {@Autowiredprivate TeacherRepository teacherRepository;//分页@Overridepublic Page<Teacher> getTeacherList(Integer page,Integer size) {    //page是基于0开始的页数,size是每页显示多少条//page的index是从0开始的,不是从1开始的Pageable pageable = new PageRequest(page, size);Page<Teacher> teacherPage = teacherRepository.findAll(pageable);return teacherPage;}}//Dao层public interface TeacherRepository extends PagingAndSortingRepository<Teacher, Integer> {}

排序举例:

//Contorller层@Controllerpublic class TeacherController {@Autowiredprivate TeacherService teacherService;@RequestMapping("/teacherShow")public String studentIntroduce(Integer page,Integer size){Page<Teacher> teacherPage = teacherService.getTeacherList(page,size);return "teacherShow";}}//Service层public interface TeacherService {Page<Teacher> getTeacherList(Integer page,Integer size);}//ServiceImp层@Service@Transactionalpublic class TeacherServiceImpl implements TeacherService {@Autowiredprivate TeacherRepository teacherRepository;//分页+排序@Overridepublic Page<Teacher> getTeacherList(Integer page,Integer size) {    //排序(根据id降序排)    Sort.Order order = new Sort.Order(Sort.Direction.DESC,"id")Sort sort = new Sort(order);//分页Pageable pageable = new PageRequest(page, size,sort);Page<Teacher> teacherPage = teacherRepository.findAll(pageable);return teacherPage;}}//Dao层public interface TeacherRepository extends PagingAndSortingRepository<Teacher, Integer> {}

4.JpaRepository:继承PagingAndSortingRespsitory接口,通过JPA规范实现了扩展的增删该查,批量操作的方法

               findAll():找到所有的实体对象
               findAll(Sort sort):找到所有的实体对象并且进行排序
               save(entities):保存多个实体对象
               flush():客户端对实体类中数据的任何改变和手写的任何SQL都是保存在客户端的内存当中,
                          只有执行flush()后,对数据库的修改就发送到数据库服务器端的数据高速缓冲区,而非数据文件中
               deleteInBatch(entities):这个批次里面删除哪些实体
   和CrudRepository中的举例是一样的,参照上面的方法就可以了,这里不再举例

   总结:

          JpaRepository继承PagingAndSortingRepository,PagingAndSortingRepository又继承 

    CrudRepository,CrudRepository又继承了Repository,总的来说,我们平时在开发中只要继承JpaRepository接口,父接口有

    的方法它都有,就相当于拥有了增删查改,分页排序等功能

5. JpaSpecificationExcutor:没有继承Repository或者他的子接口,它不属于前面接口的子接口,只是通过JPA规范

   实现了查询的方法

          (Specification是Spring Data JPA提供的一个查询规范,要做复杂的查询,类使hibernate的QBC查询)

举例:

//Contorller层@Controllerpublic class TeacherController {@Autowiredprivate TeacherService teacherService;@RequestMapping("/teacherShow")public String studentIntroduce(Integer page,Integer size){Page<Teacher> teacherPage = teacherService.getTeacherList(page,size);return "teacherShow";}}//Service层public interface TeacherService {Page<Teacher> getTeacherList(Integer page,Integer size);}//ServiceImp层@Service@Transactionalpublic class TeacherServiceImpl implements TeacherService {@Autowiredprivate TeacherRepository teacherRepository;//分页+排序@Overridepublic Page<Teacher> getTeacherList(Integer page,Integer size) {    //排序(根据id降序排)    Sort.Order order = new Sort.Order(Sort.Direction.DESC,"id")Sort sort = new Sort(order);//分页Pageable pageable = new PageRequest(page, size,sort);//查询/**root:就是我们要查询的类型(Teacher)*query:添加查询的条件*cb:构建Predicate*/Specification<Teacher> specification = new Specification<Teacher>(){@Overridepublic Predicate toPredicate(Root<Teacher> root, CriteriaQuery<?> query, CriteriaBuilder cb){//path可以获取到age属性的路径,相当于root基面包含teacher,teacher里面包含agePath path = root,get("age");//gt代表大约,表示的是返回大约30岁的return cb.get(path,30);}};Page<Teacher> teacherPage = teacherRepository.findAll(specification,pageable);return teacherPage;}}public interface TeacherRepository extends JpaRepository<Teacher, Integer>,JpaSpecificationExecutor<Teacher> {}

但是本人觉得这样写还不如自己直接写sql语句来的更快,看到大家自己的喜好选择


PS:

       这是本人对spring-data-jpa的部分见解,还有许多不足的地方,有好的意见,欢迎留言一起讨论