一、使用Spring Data JPA前的准备
(一)简介
1.JPA与Hibetnate的关系
JPA和Hibernate的关系就像JDBC和JDBC驱动的关系,JPA是规范,Hibernate除了作为ORM框架之外,它也是一种JPA实现。JPA怎么取代Hibernate呢?JDBC规范可以驱动底层数据库吗?答案是否定的,也就是说,如果使用JPA规范进行数据库操作,底层需要hibernate作为其实现类完成数据持久化工作。
2.Spring Data jpa
Spring Data JPA 让我们解脱了DAO层的操作,基本上所有CRUD都可以依赖于它来实现,在实际的工作工程中,推荐使用Spring Data JPA + ORM(如:hibernate)完成操作,这样在切换不同的ORM框架时提供了极大的方便,同时也使数据库层操作更加简单,方便解耦
3.总结:
JPA是一种规范,Hibernate实现了JPA规范,即Hibernate为JPA的一种实现;而Spring Data JPA是对JPA进行更高级的封装,让其dao编码变得更简单。
建议官网逛一逛:Spring Data JPA
(二)导包
部分其他依赖就不一个一个的列举,读者也可以根据自己实际的开发情况进行添加
<!-- Spring Data JPA 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
(三) 配置文件
#Tomcat容器相关配置
server.port=8888
#数据库配置
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/diarysystem?useSSL=false&serverTimezone=UTC&characterEncoding=utf8&allowMultiQueries=true&allowPublicKeyRetrieval=true
spring.datasource.username=root
spring.datasource.password=123456
#正向工程
spring.jpa.hibernate.ddl-auto=update
#sql显示
spring.jpa.show-sql=true
二、实操
(一)接口编写
package com.sgh.disrysystemweb.dao;
import com.sgh.disrysystemweb.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
/**
* 编写UserDao
*/
public interface UserRepository extends JpaRepository<User,Integer> {
}
(二) 实体类
package com.sgh.disrysystemweb.entity;
import lombok.Data;
import lombok.ToString;
import javax.persistence.*;
@Entity
@Data
@ToString
@Table(name="user") //对应数据库表名
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)//自增长
@Column(name = "uid") //如果不传真,默认此属性名
private Integer uid;
@Column
private String name;
@Column
private Integer age;
@Column
private String telphone;
@Column
private String email;
@Column
private String job;
public User(){
}
}
(三)测试
package com.sgh.disrysystemweb.dao;
import com.sgh.disrysystemweb.entity.User;
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.test.annotation.Rollback;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.transaction.Transactional;
/**
* @author sugha
* @version 1.0
* @description
* @date 2021/1/12 0012 22:27
*/
@RunWith(SpringJUnit4ClassRunner.class)
//@ContextConfiguration("classpath:applicationContext.xml")
@SpringBootTest
public class UserDaoTest {
@Autowired
private UserRepository usersDao;
/**
* 添加用户
*/
@Test
@Transactional// 在测试类对于事务提交方式默认的是回滚。
@Rollback(false)//取消自动回滚
public void testInsertUsers(){
User user = new User();
user.setTelphone("1234555");
user.setName("SGH");
user.setJob("java编程");
user.setEmail("123124@qq.com");
user.setAge(12);
usersDao.save(user);
}
}
三、拓宽
(一)JPA接口关系
RoleRepository是我自己创建的一个接口,QueryByExampleExecutor只是我又自己继承了,所以才有两条线。
(二)JPA主要接口使用
在使用之前先看两张截图(应该能看清楚吧,如果看不清可见官网):
在下面的接口测试中只用到了截图中的部分,但注意让大家进行扩展学习了。
1.JpaRepository接口
编写接口
package com.sgh.disrysystemweb.dao.demo;
import com.sgh.disrysystemweb.entity.Role;
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.QueryByExampleExecutor;
import javax.transaction.Transactional;
import java.util.List;
public interface RoleRepository extends JpaRepository<Role, String> {
//方法名称必须要遵循驼峰式命名规则,findBy(关键字)+属性名称(首字母大写)+查询条件(首字母大写)
//根据roleName查询
List<Role> findByRoleName(String roleName);
//根据roleName and roleCode查询
List<Role> findByRoleNameAndRoleCode(String roleName, String roleCode);
//根据roleName模糊查询
List<Role> findByRoleNameLike(String roleName);
@Query("from Role where role_Name = ?1 ")
List<Role> queryByNameHQL(String rolename);
@Query(value = "select * from Role where role_Name = ?1 ",nativeQuery = true)
List<Role> queryByRoleNameSQL(String roleName);
//
@Query("update Role set role_Name=?1 where roleid= ?2")
@Modifying //需要执行一个更新操作
@Transactional //加上事务
void updateRoleNameById(String roleName,String roleId);
}
编写映射实体类
package com.sgh.disrysystemweb.entity;
import lombok.Data;
import lombok.ToString;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import java.util.Date;
@Entity
@Data
@ToString
@Table(name="role") //对应数据库表名
public class Role {
@Id
@Column(name ="ROLEID")
private String roleid;
@Column(name ="ROLE_NAME")
private String roleName;
@Column(name ="ROLE_CODE")
private String roleCode;
@Column(name ="ROLE_TYPE")
private String roleType;
@Column(name ="ISACTIVE")
private String isactive;
@Column(name ="CREATE_DATE")
private String createDate;
@Column(name ="TENANT_ID")
private String tenantId;
@Column(name ="DTYPE")
private String dtype;
@Column(name ="REMARK")
private String remark;
@Column(name ="CREATOR")
private String creator;
@Column(name ="MODIFY_DATE")
private String modifyDate;
@Column(name ="REVISER")
private String reviser;
@Column(name ="LABEL_NAME")
private String labelName;
@Column(name ="TS")
private String ts;
@Column(name ="DR")
private Integer dr;
@Column(name ="MODIFIED_TIME")
private Date modifiedTime;
@Column(name ="CREATION_TIME")
private Date creationTime;
@Column(name ="NEW_TS")
private String newTs;
@Column(name ="ROLE_NAME2")
private String roleName2;
@Column(name ="BASEROLE_TYPE")
private String baseroleType;
@Column(name ="EXT01")
private String ext01;
@Column(name ="ORGANIZATION_ID")
private String organizationId;
}
编写测试类
package com.sgh.disrysystemweb.dao.demo;
import com.sgh.disrysystemweb.entity.Role;
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.test.annotation.Rollback;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.transaction.Transactional;
import java.util.List;
import java.util.Optional;
/**
* @author sugha
* @version 1.0
* @description
* @date 2021/1/9 0013 22:21
*/
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class RoleRepositoryTest {
@Autowired
RoleRepository roleRepository;
@Test
public void insertTest(){
Role role = new Role();
role.setRoleid("222");
role.setRoleCode("222");
role.setRemark("备注");
role.setRoleName("角色1");
role.setDr(1);
roleRepository.save(role);
}
@Test
public void findByRoleNameTest(){
List<Role> roles = roleRepository.findByRoleName("角色1");
for(Role role : roles){
System.out.println(role);
}
}
@Test
public void findByRoleNameAndRoleCode(){
List<Role> roles = roleRepository.findByRoleNameAndRoleCode("角色1", "222");
for(Role role : roles){
System.out.println(role);
}
}
@Test
public void findByRoleNameLikeTest() {
List<Role> roles = roleRepository.findByRoleNameLike("角色_");//占位符还是自己输入
for(Role role : roles){
System.out.println(role);
}
}
@Test
public void queryByNameHQLTest(){
List<Role> roles = roleRepository.queryByNameHQL("角色1");
for(Role role : roles){
System.out.println(role);
}
}
@Test
public void queryByRoleNameSQLTest(){
List<Role> roles = roleRepository.queryByRoleNameSQL("角色1");
for(Role role : roles){
System.out.println(role);
}
}
@Test
@Transactional //@Transactional与@Test 一起使用时 事务是自动回滚的。
@Rollback(false) //取消自动回滚
public void updateRoleNameByIdTest(){
roleRepository.updateRoleNameById("角色2","222");
}
}
2.JPASpecificationExecutor接口
JpaSpecificationExecutor接口的使用一般要和Repository体系的接口一起使用
注意:
在讲述原理的时候Dao对象其实是注入了一个代理对象,通过继承Repository体系接口完成代理对象SimpleJpaRepository实现类对象的注入。而JpaSpecificationExecutor对象不在Repository接口体系内那么就无法完成对象注入,所以要使用JpaSpecificationExecutor对象必须要实现Repository体系接口
3.PagingAndSortingRepository接口
该接口提供了分页与排序的操作,注意:该接口继承了CrudRepository接口
接口编写
package com.sgh.disrysystemweb.dao.demo;
import com.sgh.disrysystemweb.entity.Role;
import org.springframework.data.repository.PagingAndSortingRepository;
public interface RoleRepositoryPagingAndSorting extends PagingAndSortingRepository<Role,String> {
}
测试类编写
package com.sgh.disrysystemweb.dao.demo;
import com.sgh.disrysystemweb.entity.Role;
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.test.context.junit4.SpringJUnit4ClassRunner;
//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 java.util.List;
/**
* @author sugha
* @version 1.0
* @description
* @date 2021/1/10 0014 10:06
*/
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class RoleRepositoryPagingAndSortingTest {
@Autowired
private RoleRepositoryPagingAndSorting roleRepositoryPagingAndSorting;
@Test
public void testPagingAndSortingRepositorySort() {
//Order 定义了排序规则
Sort.Order order=new Sort.Order(Sort.Direction.DESC,"roleid");
//Sort对象封装了排序规则
Sort sort=Sort.by(order);
List<Role> list= (List<Role>) roleRepositoryPagingAndSorting.findAll(sort);
for (Role Role:list){
System.out.println(Role);
}
}
@Test
public void testPagingAndSortingRepositoryPaging() {
//Pageable:封装了分页的参数,当前页,煤业显示的条数。注意:它的当前页是从0开始
//PageRequest(page,size):page表示当前页,size表示每页显示多少条
Pageable pageable= PageRequest.of(1,2);
Page<Role> page=this.roleRepositoryPagingAndSorting.findAll(pageable);
System.out.println("数据的总条数:"+page.getTotalElements());
System.out.println("总页数:"+page.getTotalPages());
List<Role> list=page.getContent();
for (Role Role:list){
System.out.println(Role);
}
}
@Test
public void testPagingAndSortingRepositorySortAndPaging() {
Sort sort=Sort.by(new Sort.Order(Sort.Direction.DESC,"roleid"));
Pageable pageable=PageRequest.of(0,2,sort);
Page<Role> page=this.roleRepositoryPagingAndSorting.findAll(pageable);
System.out.println("数据的总条数:"+page.getTotalElements());
System.out.println("总页数:"+page.getTotalPages());
List<Role> list=page.getContent();
for (Role Role:list){
System.out.println(Role);
}
}
}
4.QueryByExampleExecutor接口
QBE是一种查询技术,允许动态创建查询,并且不需要编写包含字段名称的查询。
5.CrudRepository接口
CrudRepository接口,主要是完成一些增删改查的操作。注意:CrudRepository接口继承了Repository接口。
编写接口
package com.sgh.disrysystemweb.dao.demo;
import com.sgh.disrysystemweb.entity.Role;
import org.springframework.data.repository.CrudRepository;
/**
* @author sugha
* @version 1.0
* @description
* @date 2021/1/10 0014 11:33
*/
public interface RoleRepositoryCrudRepository extends CrudRepository<Role,String> {
}
编写测试类
package com.sgh.disrysystemweb.dao.demo;
import com.sgh.disrysystemweb.entity.Role;
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.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.List;
import java.util.Optional;
/**
* @author sugha
* @version 1.0
* @description
* @date 2021/1/10 0014 11:34
*/
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class RoleRepositoryCrudRepositoryTest {
@Autowired
private RoleRepositoryCrudRepository roleRepositoryCrudRepository;
@Test
public void testCrudRepositorySave() {
Role role = new Role();
role.setRoleid("12312312");
role.setRoleName("黑暗猎手");
role.setRoleCode("VN");
roleRepositoryCrudRepository.save(role);
}
@Test
public void testCrudRepositoryUpdate() {
Role role = new Role();
role.setRoleid("222223");
role.setRoleName("光辉");
role.setRoleCode("GHHHHHHH");
this.roleRepositoryCrudRepository.save(role);
}
@Test
public void testCrudRepositoryFindOne() {
Optional<Role> role = roleRepositoryCrudRepository.findById("222223");
System.out.println(role);
}
@Test
public void testCrudRepositoryFindAll() {
List<Role> list = (List<Role>) this.roleRepositoryCrudRepository.findAll();
for (Role user : list) {
System.out.println(user);
}
}
@Test
public void testCrudRepositoryDeleteById() {
roleRepositoryCrudRepository.deleteById("222223");
}
}