详解Spring Data JPA
来源:互联网 发布:软件造价评估公司 编辑:程序博客网 时间:2024/06/14 09:14
1.什么是SpringData?
Spring Data 项目的目的是为了简化构建基于 Spring 框架应用的数据访问计数,包括非关系数据库、Map-Reduce 框架、云数据服务等等;另外也包含对关系数据库的访问支持。
Spring Data 包含多个子项目:
Commons - 提供共享的基础框架,适合各个子项目使用,支持跨数据库持久化
Hadoop - 基于 Spring 的 Hadoop 作业配置和一个 POJO 编程模型的 MapReduce 作业
Key-Value - 集成了 Redis 和 Riak ,提供多个常用场景下的简单封装
Document - 集成文档数据库:CouchDB 和 MongoDB 并提供基本的配置映射和资料库支持
Graph - 集成 Neo4j 提供强大的基于 POJO 的编程模型
Graph Roo AddOn - Roo support for Neo4j
JDBC Extensions - 支持 Oracle RAD、高级队列和高级数据类型
JPA - 简化创建 JPA 数据访问层和跨存储的持久层功能
Mapping - 基于 Grails 的提供对象映射框架,支持不同的数据库
Examples - 示例程序、文档和图数据库
Guidance - 高级文档
<span style="font-family:Comic Sans MS;font-size:18px;">/** * @FileName: PersonRepotory.java * @Package:com.tgb.springdata.Entity * @Description: TODO * @author: LUCKY * @date:2015年11月8日 下午6:38:58 * @version V1.0 */package com.tgb.springdata.Entity;import java.util.Date;import java.util.List;import org.hibernate.type.TrueFalseType;import org.springframework.data.jpa.repository.JpaRepository;import org.springframework.data.jpa.repository.JpaSpecificationExecutor;import org.springframework.data.jpa.repository.Modifying;import org.springframework.data.jpa.repository.Query;import org.springframework.data.jpa.repository.support.JpaRepositoryFactory;import org.springframework.data.repository.CrudRepository;import org.springframework.data.repository.PagingAndSortingRepository;import org.springframework.data.repository.Repository;import org.springframework.data.repository.query.Param;/** * @ClassName: PersonRepotory * @Description: TODO * @author: LUCKY * @date:2015年11月8日 下午6:38:58 *//* * 1.Repository是一个空接口,即是一个标记接口 * 2.若我们定义的接口继承了Repository,则该接口会被IOC容器识别为一个Repository Bean * 注入到IOC容器中,进而可以在该接口中定义满足一定规则的接口 * 3.实际上也可以通过一个注解@RepositoryDefination 注解来替代Repository接口 *//* * 在Repository子接口中声明方法 * 1.不是随便声明的,而需要符合一定的规范 * 2.查询方法以find|read|get开发 * 3.涉及条件查询,条件的属性需要定义关键字连接 * 4.要注意的额是,条件的属性以字母大写 * 5.支持属性的级联查询,若当前类有符合条件的属性,则优先使用,则不使用级联属性 * 若需要使用级联属性,则属性之间使用——进行连接 *///@RepositoryDefinition(domainClass=Person.class,idClass=Integer.class)public interface PersonRepotory extends JpaRepository<Person,Integer>,JpaSpecificationExecutor<Person>,PersonDao {//根据lastname,来获取对应的PersonPerson getByLastName(String lastName);//Where lastName like ?% and id<?List<Person> getByLastNameStartingWithAndIdLessThan(String lastName,Integer id);//Where lastName like ?% and id<?List<Person> getByLastNameEndingWithAndIdLessThan(String lastName,Integer id);//where email In(?,?,?) Or birth < ?List<Person> getByEmailInOrBirthLessThan(List<String> emails,Date birth);//where a.id>?List<Person> getByAddressIdGreaterThan(Integer id);//查询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=?1 AND P.email=?2")List<Person> testQueryAnnotationParams1(String lastName,String email);//为@Query注解传递参数的方式2:使用命名参数方式@Query("SELECT P FROM Person P where P.lastName=:lastName AND P.email=:email")List<Person> testQueryAnnotationParams2(@Param("email")String email,@Param("lastName")String lastName);//Spring Data 运行在占位符上添加%%@Query("select p from Person p where p.lastName like %?1% or p.email like %?2%")List<Person> testQueryAnnotationLikeParam(String lastName,String email);//设置nativeQuery=true 可以使用原生的sql查询@Query(value="SELECT count(id) FROM jpa_persons",nativeQuery=true)public long getTotalCount();//可以通过自定义的JPQL 完成update和delete操作,注意:JPQL不支持Insert操作//在@Query注解中编写JPQL语句,但必须使用@Modify进行修饰,以通知SpringData,这是一个Update或者Delete//Update或者delete操作,需要使用事务,此时需要定义Service层,在service层的方法上添加事务操作//默认情况下,SpringData的每个方法上有事务,但都是一个只读事务,他们不能完成修改操作@Modifying@Query("update Person p set p.email=:email where id=:id")void updatePersonEmail(@Param("id")Integer id,@Param("email")String email);}</span>
在Spring Data JPA中通过继承接口就可以了,下面来看一下是如何来调用的
<span style="font-family:Comic Sans MS;font-size:18px;">/** * @FileName: SpringDataTest.java * @Package:com.tgb.test * @Description: TODO * @author: LUCKY * @date:2015年11月8日 下午5:35:37 * @version V1.0 */package com.tgb.test;import static org.junit.Assert.*;import java.sql.SQLException;import java.util.ArrayList;import java.util.Arrays;import java.util.Date;import java.util.List;import javax.persistence.criteria.CriteriaBuilder;import javax.persistence.criteria.CriteriaQuery;import javax.persistence.criteria.Path;import javax.persistence.criteria.Predicate;import javax.persistence.criteria.Root;import javax.sql.DataSource;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import org.springframework.data.domain.Page;import org.springframework.data.domain.PageRequest;import org.springframework.data.domain.Pageable;import org.springframework.data.domain.Sort;import org.springframework.data.domain.Sort.Direction;import org.springframework.data.domain.Sort.Order;import org.springframework.data.jpa.domain.Specification;import com.tgb.springdata.Entity.Person;import com.tgb.springdata.Entity.PersonRepotory;import com.tgb.springdata.Service.PersonService;/** * @ClassName: SpringDataTest * @Description: TODO * @author: LUCKY * @date:2015年11月8日 下午5:35:37 */public class SpringDataTest {private PersonRepotory personRepotory=null;private PersonService personService;private ApplicationContext ctx=null;{ctx=new ClassPathXmlApplicationContext("applicationContext.xml"); personRepotory=ctx.getBean(PersonRepotory.class); personService=ctx.getBean(PersonService.class);}@Testpublic void testKeyWorlds(){List<Person> persons=personRepotory.getByLastNameStartingWithAndIdLessThan("BB", 10);System.out.println(persons);List<Person> persons1=personRepotory.getByLastNameEndingWithAndIdLessThan("BB", 10);System.out.println(persons);System.out.println(persons1);persons=personRepotory.getByEmailInOrBirthLessThan(Arrays.asList("aa@qq.com","bb@qq.com"),new Date());System.out.println(persons.size());}@Testpublic void testDataSource() throws SQLException{DataSource dataSource=ctx.getBean(DataSource.class);System.out.println(dataSource.getConnection());}@Testpublic void TestJpa(){}@Testpublic void testKeyWorlds2(){List<Person> persons=personRepotory.getByAddressIdGreaterThan(1);System.out.println(persons);}@Testpublic void testQueryAnnotation(){Person person=personRepotory.getMaxIdPerson();//System.out.println(person);List<Person> persons=personRepotory.testQueryAnnotationParams1("AA", "bb");System.out.println(persons);List<Person> persons1=personRepotory.testQueryAnnotationParams2("bb", "AA");System.out.println(persons1);}@Testpublic void testModifing(){//personRepotory.updatePersonEmail(1, "@@qq.com");personService.updatePersonEmail("aa@aa", 1);}@Testpublic void testQueryLikeAnnotationParam(){List<Person> persons=personRepotory.testQueryAnnotationLikeParam("%AA%", "%b%");System.out.println(persons);long count=personRepotory.getTotalCount();System.out.println(count);}@Testpublic void HelloWorldSpringData(){PersonRepotory personRepotory=ctx.getBean(PersonRepotory.class);System.out.println(personRepotory.getClass().getName());Person person=personRepotory.getByLastName("AA");System.out.println(person);}@Testpublic void testCrudRepository(){List<Person> persons=new ArrayList<Person>();for (int i = 1; i < 10000; i++) {Person person=new Person();person.setBirth(new Date());person.setEmail("@2"+i+" com");persons.add(person);}long startTime=System.currentTimeMillis();personService.savePersons(persons);long endTime=System.currentTimeMillis();System.out.println((endTime-startTime)/1000);}@Testpublic void testPagingAndSortingRespository(){//pageNumber是从0开始的 int pageNumber=4; int pageSize=5; //PageAble 接口通常用的是PageRequest实现类,其中封装了需要分页的信息 //排序相关的,sor封装了排序的信息 Order order1=new Order(Direction.DESC, "id"); Order order2=new Order(Direction.DESC, "email"); Sort sort=new Sort(order1,order2); Pageable pageable=new PageRequest(pageNumber, pageSize,sort);Page<Person> page=personRepotory.findAll(pageable);System.out.println("总记录数"+page.getTotalElements());System.out.println("当前第几页"+page.getNumber());System.out.println("总页数"+page.getTotalPages());System.out.println("当前页面的List"+page.getContent());System.out.println("当前页面的记录数"+page.getNumberOfElements());}@Testpublic void testJpaRepository(){Person person=new Person();person.setBirth(new Date());person.setEmail("aa");person.setLastName("xyz");personRepotory.saveAndFlush(person);}/* * 实现带查询条件的分页效果 id>5 * 调用JpaSpecificationExecutor的page<T> findAll(Speciation<T>,PageAble pageable) * specification:封装了JPA Criteria 查询的条件 * pageable:封装了请求分页的消息,例如pageno,pagesize,sort */@Testpublic void testJpaSpeciationExecutor(){int pageNo=0;int pageSize=5;PageRequest pageRequest=new PageRequest(pageNo, pageSize);//通常使用Specification 的匿名内部类,Specification<Person> specification=new Specification<Person>() {/* * @param root:代表的查询的实体类 * @param query:可以从中得到Root对象,即告知JPA Criteria查询要查询哪一个实体类, * 还可以来添加查询条件,还可以结合EntityManager对象得到最终查询的TypedQuery 对象 * @Param cb:criteriabuildre对象,用于创建Criteria相关的对象工程,当然可以从中获取到predicate类型 * @return:代表一个查询条件 */@Overridepublic Predicate toPredicate(Root<Person> root,CriteriaQuery<?> query, CriteriaBuilder cb) {//Path path=root.get("id");//Predicate predicate=cb.gt(path, 5);Predicate p1=cb.like(root.get("id").as(String.class), "%"+"1"+"%");Predicate p2=cb.equal(root.get("lastName").as(String.class), "sd");Predicate p3=cb.like(root.get("email").as(String.class), "%s%");//构建组合的Predicate示例:Predicate p = cb.and(p3,cb.or(p1,p2));return p;}};Page<Person> page=personRepotory.findAll(specification,pageRequest);System.out.println("总记录数"+page.getTotalElements());System.out.println("当前第几页"+page.getNumber());System.out.println("总页数"+page.getTotalPages());System.out.println("当前页面的List"+page.getContent());System.out.println("当前页面的记录数"+page.getNumberOfElements());}@Testpublic void testCustomRepositoryMethod(){personRepotory.test();}}</span>
或许会感到奇怪,为何Dao只单纯的是一个接口,没有实现类呢?其实这就是Spring Data JPA为我们封装了,只要按照Spring Data JPA的规范来定义,就会自动为我们生成一个默认的代理实现类。
3.Repository 接口
//使用@Query注解可以自定义JPQL语句,语句可以实现更灵活的查询
@Query("SELECT p FROM Person p WHERE p.id=(SELECT max(p2.id) FROM Person p2)")
Person getMaxIdPerson();
5.@Modifying 注解
@Query 与 @Modifying这两个annotation一起声明,可定义个性化更新操作,例如只涉及某些字段更新时最为常用,示例如下
//可以通过自定义的JPQL 完成update和delete操作,注意:JPQL不支持Insert操作
//在@Query注解中编写JPQL语句,但必须使用@Modify进行修饰,以通知SpringData,这是一个Update或者Delete
//Update或者delete操作,需要使用事务,此时需要定义Service层,在service层的方法上添加事务操作
//默认情况下,SpringData的每个方法上有事务,但都是一个只读事务,他们不能完成修改操作
@Modifying
@Query("update Person p set p.email=:email where id=:id")
void updatePersonEmail(@Param("id")Integer id,@Param("email")String email);
更多有关的内容,请参考http://blog.csdn.net/z69183787/article/details/30265243
- Spring Data JPA 详解
- Spring Data Jpa 详解
- 详解Spring Data JPA
- spring-data-jpa详解
- Spring Data JPA详解
- 详解Spring Data JPA
- Spring data jpa详解
- 详解Spring Data JPA
- spring data jpa使用详解
- spring data jpa使用详解
- (转载)Spring data jpa 详解
- Spring Data jpa搭建+配置详解
- Spring Data Jpa 详解 (配置篇)
- Spring Data Jpa 详解 (配置篇)
- Spring-data-jpa详解,全方位介绍。
- Spring Data JPA @EnableJpaRepositories配置详解
- Spring Data Jpa 详解 (配置篇)
- Spring Data Jpa 详解 (配置篇)
- 一起做RGB-D SLAM (4)
- web.xml配置详解
- JBoss7.1配置Oracle11g数据源,详细图解
- Redis KVStore 在阿里云环境下的性能报告及问题
- [IOS 开发] 利用UIWebView 加载GIF动画
- 详解Spring Data JPA
- Delphi中的操作二进制文件的两个重要函数
- 一起做RGB-D SLAM (5)
- 杭电1048--输出输出格式控制
- SecureCrt连接Linux操作tomcat
- HTML文本编辑
- 【扣丁学堂】让程序员的开发项目不再半途而废
- jenkins调用webdriver
- 一起做RGB-D SLAM (6)