一、简介

  SpringDataJpa是 JPA规范的一个很好的实现,简化了开发的复杂度,极大提升了开发的效率。SpringDataJpa通过 Repository接口及子接口可以很方便的实现持久化操作。

  SpringDataJpa的API在线手册:https://docs.spring.io/spring-data/jpa/docs/2.1.0.RELEASE/api/

  简单的看下 Repository 类层次结构图关系:

  

  Repository:空的父接口,即是一个标记接口。

   CrudRepository:Repository的子接口,提供CRUD操作

   PagingAndSortingRepository:CrudRepository的子接口,增加 分页 和 排序的功能

  JpaRepository:PagingAndSortingRepository、QueryByExampleExecutor的子接口,增加 批量操作 以及 QBE查询

  SimpleJpaRepository:实现了JpaRepository 和 JpaSpecificationExecutor 接口,构造函数中传入 EntityManager。类上注解了@Transactional(readOnly = true),对于CUD的方法使用了注解@Transactional,局部有限原则。各种方法最终的实现都依托于 EntityManager来完成。

二、使用

  1、创建springboot项目 springdata-jpa

  2、src/main/resources 目录下新建 application.properties,内容如下:

db.driverClass=com.mysql.jdbc.Driver
db.jdbcUrl=jdbc:mysql://localhost:3310/boot?useUnicode=true&characterEncoding=UTF-8&useSSL=false
db.username=root
db.password=
spring.jpa.properties.hibernate.show_sql=true
spring.jpa.properties.hibernate.format_sql=true
#修改实体类的匹配命名规则,主要影响@column(name="")配置,默认是驼峰匹配法
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

  3、创建 DataSource configuration:

package com.cfang.confingurations;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import com.alibaba.druid.pool.DruidDataSource; @Configuration
public class DataSourceConfigurations { @Value("${db.driverClass:com.mysql.jdbc.Driver}")
private String driverClass;
@Value("${db.jdbcUrl}")
private String jdbcUrl;
@Value("${db.username}")
private String username;
@Value("${db.password}")
private String password;
@Value("${initialSize:10}")
private Integer initialSize; //初始化连接池个数
@Value("${maxActive:20}")
private Integer maxActive; //最大连接数
@Value("${maxWait:60000}")
private Long maxWait; //获取连接等待超时时间,单位毫秒
@Value("${timeBetweenEvictionRunsMillis:60000}")
private Long timeBetweenEvictionRunsMillis; //间隔多久进行一次检测,检测回收需要关闭的空闲链接,单位毫秒
@Value("${minEvictableIdleTimeMillis:300000}")
private Long minEvictableIdleTimeMillis; //定义一个连接在池中的最小生存时间,单位毫秒
@Value("${validationQuery:select 1 from dual}")
private String validationQuery; //用来检测连接是否有效的sql
@Value("${testWhileIdle:true}")
private Boolean testWhileIdle; //申请连接的时候是否检测。如果空间时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效
@Value("${testOnBorrow:false}")
private Boolean testOnBorrow;
@Value("${testOnReturn:false}")
private Boolean testOnReturn; //归还连接的时候,是否validationQuery检查连接的有效性,true执行的话,降低性能
@Value("${poolPreparedStatements:false}")
private Boolean poolPreparedStatements; //是否打开pscache
@Value("${maxPoolPreparedStatementPerConnectionSize:20}")
private int maxPoolPreparedStatementPerConnectionSize; //指定每个连接的pscache的大小 @Bean
public DataSource initDataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(driverClass);
dataSource.setUrl(jdbcUrl);
dataSource.setUsername(username);
dataSource.setPassword(password);
dataSource.setInitialSize(initialSize);
dataSource.setMaxActive(maxActive);
dataSource.setMaxWait(maxWait);
dataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
dataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
dataSource.setValidationQuery(validationQuery);
dataSource.setTestWhileIdle(testWhileIdle);
dataSource.setTestOnBorrow(testOnBorrow);
dataSource.setTestOnReturn(testOnReturn);
dataSource.setPoolPreparedStatements(poolPreparedStatements);
if(poolPreparedStatements) {
dataSource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
}
return dataSource;
}
}

  4、创建User实体

package com.cfang.entity;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table; import lombok.Data; @Entity
@Table(name = "tb_user")
@Data
public class TblUserEntity { @Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private int id;
@Column(name = "name")
private String name;
@Column(name = "password")
private String password;
@Column(name = "age")
private int age;
}

  5、创建持久化操作Repository:

package com.cfang.repository;

import java.util.List;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
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.repository.query.Param; import com.cfang.entity.TblUserEntity; public interface UserRepository extends JpaRepository<TblUserEntity, Integer>, JpaSpecificationExecutor<TblUserEntity>{ /**
* springdata关键字命名方法,可不写实现
*/
TblUserEntity findByName(String name);
TblUserEntity findByNameAndAge(String name, int age);
List<TblUserEntity> findByNameLikeAndAge(String name, int age); Page<TblUserEntity> findUserPageByNameLike(String name, Pageable pageable); /**
* JPQL
*/
@Query(value = "from TblUserEntity where id=?1", nativeQuery = false)
TblUserEntity readIdByJPQL(int id); @Query(value = "select * from tb_user where id=:id", nativeQuery = true)
TblUserEntity readIdBySQL(int id); @Modifying
@Query(value = "update TblUserEntity set name=?2 where id=?1", nativeQuery = false)
int updateUserNameByIdJPQL(int id, String name); @Modifying
@Query(value = "update tb_user set name=:name where id=:id", nativeQuery = true)
int updateUserNameByIdSQL(@Param("id")int id, @Param("name")String name); @Query(value = "from TblUserEntity where name like %?1%", nativeQuery = false)
List<TblUserEntity> findUserByNameJPQL(String name); @Query(value = "select * from tb_user where name like %:name%", nativeQuery = true)
List<TblUserEntity> findUserByNameSQL(String name); }

  6、创建 junit 测试

package com.cfang.repository;

import java.util.List;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root; import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
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.jpa.domain.Specification;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.transaction.annotation.Transactional; import com.alibaba.fastjson.JSON;
import com.cfang.SpringDataJpaApplication;
import com.cfang.entity.TblUserEntity;
import com.google.common.collect.Lists; import lombok.extern.slf4j.Slf4j; @Slf4j
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = {SpringDataJpaApplication.class})
@WebAppConfiguration
public class UserTest { @Autowired
private UserRepository userRepository; @Test
public void findByName() {
TblUserEntity entity = userRepository.findByName("lisi");
log.info("result:{}", JSON.toJSONString(entity));
} @Test
public void findByNameAndAge() {
TblUserEntity entity = userRepository.findByNameAndAge("lisi", );
log.info("result:{}", JSON.toJSONString(entity));
} @Test
public void findByNameLikeAndAge() {
List<TblUserEntity> entity = userRepository.findByNameLikeAndAge("li%", );
log.info("result:{}", JSON.toJSONString(entity));
} @Test
public void readIdByJPQL() {
TblUserEntity entity = userRepository.readIdByJPQL();
log.info("result:{}", JSON.toJSONString(entity));
} @Test
public void readIdBySQL() {
TblUserEntity entity = userRepository.readIdBySQL();
log.info("result:{}", JSON.toJSONString(entity));
} @Test
@Transactional
@Rollback(false)
public void updateUserNameByIdJPQL() {
int result = userRepository.updateUserNameByIdJPQL(, "wangwu");
log.info("result:{}", result);
} @Test
@Transactional
@Rollback(false)
public void updateUserNameByIdSQL() {
int result = userRepository.updateUserNameByIdSQL(, "wangwu2");
log.info("result:{}", result);
} @Test
public void findUserByNameJPQL() {
List<TblUserEntity> entity = userRepository.findUserByNameJPQL("li");
log.info("result:{}", JSON.toJSONString(entity));
} @Test
public void findUserByNameSQL() {
List<TblUserEntity> entity = userRepository.findUserByNameSQL("li");
log.info("result:{}", JSON.toJSONString(entity));
} @Test
public void findUserPageByNameLike() {
Pageable pageable = PageRequest.of(, , new Sort(Sort.Direction.DESC, "id"));
Page<TblUserEntity> entity = userRepository.findUserPageByNameLike("li%", pageable);
log.info("result:{}", JSON.toJSONString(entity));
} @Test
public void testSpecification() {
Pageable pageable = PageRequest.of(, , Sort.Direction.DESC, "id");
String name = "li";
Specification<TblUserEntity> specification = new Specification<TblUserEntity>() {
@Override
public Predicate toPredicate(Root<TblUserEntity> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
List<Predicate> conditions = Lists.newArrayList();
Predicate condition = null;
condition = criteriaBuilder.like(root.get("name"), "%" + name + "%");
conditions.add(condition);
condition = criteriaBuilder.greaterThan(root.get("id"), );
conditions.add(condition); Predicate[] arr = new Predicate[conditions.size()];
// return criteriaBuilder.and(conditions.toArray(arr));
query.where(conditions.toArray(arr));
return null;
}
};
Page<TblUserEntity> result = userRepository.findAll(specification, pageable);
log.info("result:{}", JSON.toJSONString(result));
} }

  ps:在进行 repository 的CUD操作的时候,必须加事务支持 @Transactional,否则会报错(截取部分出错信息):

org.springframework.dao.InvalidDataAccessApiUsageException: Executing an update/delete query; nested exception is javax.persistence.TransactionRequiredException: Executing an update/delete query
Caused by: javax.persistence.TransactionRequiredException: Executing an update/delete query

三、总结

  数据进行持久化操作的时候,都是需要一个对象来进行相关操作的,原生的Hibernate中使用Session,JPA中使用EntityManager,MyBatis中使用SqlSession。上述工程中,在主类main方法中可添加如下进行查看:

@Bean
public Object testTransactionManager(PlatformTransactionManager manager) {
System.out.println("TransactionManager is : " + manager.getClass().getName());
return new Object();
}

  SpringDataJpa提供了丰富的CRUD构造的方法,具体可根据实际情况查询使用。

SpringDataJPA使用的更多相关文章

  1. Spring-data-jpa详解,全方位介绍。

    本篇进行Spring-data-jpa的介绍,几乎涵盖该框架的所有方面,在日常的开发当中,基本上能满足所有需求.这里不讲解JPA和Spring-data-jpa单独使用,所有的内容都是在和Spring ...

  2. 【java】spring-data-jpa 集成hibernate实现多条件分页查询

    初次接触spring-data-jpa,实现多条件分页查询. 基础环境 Spring Boot+spring-data-jpa+hibernate+mysql 1.接口 要继承这个接口,这个接口提供了 ...

  3. 【原创】纯干货,Spring-data-jpa详解,全方位介绍。

    本篇进行Spring-data-jpa的介绍,几乎涵盖该框架的所有方面,在日常的开发当中,基本上能满足所有需求.这里不讲解JPA和Spring-data-jpa单独使用,所有的内容都是在和Spring ...

  4. Spring-Data-JPA学习

    Spring-Data-JPA结构图 网址: http://blog.sina.com.cn/s/blog_667ac0360102ecsf.html

  5. 纯干货,Spring-data-jpa详解,全方位介绍

    本篇进行Spring-data-jpa的介绍,几乎涵盖该框架的所有方面,在日常的开发当中,基本上能满足所有需求.这里不讲解JPA和Spring-data-jpa单独使用,所有的内容都是在和Spring ...

  6. spring-data-jpa 中,如果使用了one-to-many , many-to-one的注释,会在Jackson进行json字符串化的时候出现错误

    问题: spring-data-jpa 中,如果使用了one-to-many , many-to-one的注释,会在Jackson 2.7.0 进行json字符串化的时候出现错误. 解决办法: 通过在 ...

  7. SpringDataJPA入门就这么简单

    一.SpringData入门 在上次学SpringBoot的时候,那时候的教程就已经涉及到了一点SpringData JPA的知识了.当时还是第一次见,觉得也没什么大不了,就是封装了Hibernate ...

  8. Spring Boot with Spring-Data-JPA学习案例

    0x01 什么是Spring Boot? Spring Boot是用来简化Spring应用初始搭建以及开发过程的全新框架,被认为是Spring MVC的"接班人",和微服务紧密联系 ...

  9. Spring-Data-JPA整合MySQL和配置

    一.简介 (1).MySQL是一个关系型数据库系统,是如今互联网公司最常用的数据库和最广泛的数据库.为服务端数据库,能承受高并发的访问量. (2).Spring-Data-Jpa是在JPA规范下提供的 ...

  10. sssp-springmvc+spring+spring-data-jpa增删改查

    环境:IDE:eclipse.jdk1.7.mysql5.7.maven 项目结构图 上面目录结构你可以自己创建 搭建框架 首先加入maven依赖包以及相关插件 <dependencies> ...

随机推荐

  1. hihocode 1584 : Bounce (找规律)(2017 北京网络赛G)

    题目链接 比赛时随便找了个规律,然后队友过了.不过那个规律具体细节还挺烦的.刚刚偶然看到Q巨在群里提到的他的一个思路,妙啊,很好理解,而且公式写起来也容易.OrzQ巨 #include<bits ...

  2. react native 实现TODO APP

    前端有一个todo app非常适合入门练手 react-native 实现todo app:https://github.com/nwgdegitHub/TODO_RN.git

  3. web上传大文件(>4G)有什么解决方案?

    众所皆知,web上传大文件,一直是一个痛.上传文件大小限制,页面响应时间超时.这些都是web开发所必须直面的. 本文给出的解决方案是:前端实现数据流分片长传,后面接收完毕后合并文件的思路. 实现文件夹 ...

  4. POJ 1011 Sticks(搜索 && 剪枝 && 经典)

    题意 : 有n根木棍(n<=64),它们由一些相同长度的木棍切割而来,给定这n根木棍的长度,求使得原来长度可能的最小值. 分析 : 很经典的深搜题目,我们发现答案只可能是所有木棍长度总和的因数, ...

  5. Linux入门 文本编辑器

    Vim vi -r file # 在上次使用vi编辑时发生崩溃,恢复file 在编辑多个文件时候 :n 下一个文件 :e# 回到刚才编辑的文件 撤销操作 撤销前一个命令 输入"u" ...

  6. 20180829-Java多线程编程

    Java 多线程编程 Java给多线程编程提供了内置的支持.一个多线程程序包含两个或多个能并发运行的部分. 程序的每一部分都称作一个线程,并且每个线程定义了一个独立的执行路径. 多线程是多任务的一种特 ...

  7. java读取ldif文件并创建新的节点

    所需jar包ldap.jar. jldap-4.3-source.jar http://www.java2s.com/Code/Jar/l/Downloadldapjar.htm 浏览器输入http: ...

  8. Redis之Java客户端Jedis

    导读 Redis不仅使用命令客户端来操作,而且可以使用程序客户端操作. 现在基本上主流的语言都有客户端支持,比如Java.C.C#.C++.php.Node.js.Go等. 在官方网站里列一些Java ...

  9. leetcode-mid-array-49 Group Anagrams

    mycode  95.35% 思路:构建字典 class Solution(object): def groupAnagrams(self, strs): """ :ty ...

  10. day03-Python基础

    1:函数 定义: 函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可 特性: 减少重复代码 使程序变的可扩展 使程序变得易维护 函数定义: def sayh ...