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

一.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.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
		http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
		http://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.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
		http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
		http://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_web
jdbc.driver= com.mysql.jdbc.Driver
jdbc.user = root
jdbc.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层:

@Query
public 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")
@Modifying
public 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
@Transactional
public class SidebarServiceImpl implements SidebarService {

	@Autowired
	private SidebarRepository sidebarRepository;
	
	@Override
	public void save(StudentsInf studentsInf) {
		sidebarRepository.save(studentsInf);
	}

}

//controller层:

@Controller
public class SidebarController {

	@Autowired
	private 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层
@Controller
public class TeacherController {

	@Autowired
	private 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
@Transactional
public class TeacherServiceImpl implements TeacherService {

	@Autowired
	private TeacherRepository teacherRepository;
	
	//分页
	@Override
	public 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层
@Controller
public class TeacherController {

	@Autowired
	private 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
@Transactional
public class TeacherServiceImpl implements TeacherService {

	@Autowired
	private TeacherRepository teacherRepository;
	
	//分页+排序
	@Override
	public 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层
@Controller
public class TeacherController {

	@Autowired
	private 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
@Transactional
public class TeacherServiceImpl implements TeacherService {

	@Autowired
	private TeacherRepository teacherRepository;
	
	//分页+排序
	@Override
	public 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>(){
			@Override
			public Predicate toPredicate(Root<Teacher> root,
										 CriteriaQuery<?> query,
										 CriteriaBuilder cb){
				//path可以获取到age属性的路径,相当于root基面包含teacher,teacher里面包含age
				Path 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的部分见解,还有许多不足的地方,有好的意见,欢迎留言一起讨论



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值