spring data jpa
JPA(java persistence api)
JPA是Java Persistence API的简称,中文名Java持久层API,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。 [1]
Sun引入新的JPA ORM规范出于两个原因:其一,简化现有Java EE和Java SE应用开发工作;其二,Sun希望整合ORM技术,实现天下归一。
JPA底层采用hibernate,
Spring Data
Spring Data项目目的是为了简化基于spring框架对持久化层的操作技术,包含了关系型数据库、非关系型数据库,map-reduce框架等。
- Spring Data特点
提供了统一的api对持久化层进行操作;主要是通过spring data commons项目实现。让我们使用关系型数据库或非关系型数据库时都能给予一个统一的标准,这个标准中包含了crud,分页排序等。
- Spring Data提供了统一的Repository接口,可以实现对关系型数据库或非关系型数据库的操作
- Spring Data提供了数据访问的模版
如:
JdbcTemplate
RedisTemplate
MongoDbTemplate
Spring Data Jpa
是spring data家族中的一个项目,可以轻松的实现基于Jpa的数据操作。
启动器和依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>2109q-boot-test1</artifactId>
<groupId>com.sofwin</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>2109q-boot-jpa</artifactId>
<dependencies>
<!-- jpa 和jdbc相关的依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
</dependencies>
</project>
配置jpa
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql:///db
username: root
password: 123456
hikari:
minimum-idle: 2 # 最小连接数
idle-timeout: 200000 # 空闲连接的最大存活时间
maximum-pool-size: 6 # 连接池中的最大连接数
connection-test-query: select 1 # 测试连接是否可用的语句
connection-timeout: 200000 # 数据库连接的超时时
jpa:
show-sql: true # 打印SQL语句
hibernate:
ddl-auto: none # 主要是基于hibernate orm框 对象关系模型
# none 不对数据库中的表进行新增和更新
# create 每次启动项目都根据对象关系模型来生成数据库中的表
# update 每次启动项目都根据对象关系模型来更新数据库中的表
创建实体类完善对象关系模型
- @Entity
声明当前类是实体类,也就是说这个类需要和数据库中的某个表进行映射。
- @Table
声明当前实体类和哪个表进行关系映射
- @Id
声明属性中用于映射主键的属性
- @GeneratedValue
主键策略
table :从一张表中来获取主键信息
IDENTITY:主键自增 mysql
SEQUENCE:根据数据库的序列来生成逐渐,数据库底层要支持序列 oracle
AUTO:由程序来控制主键的生成
- @Column
声明属性和字段的映射关系
package com.sofwin.pojo;
import lombok.Data;
import javax.persistence.*;
/**
* ClassName: User
* Description: 实体类 对象 --sys_user关系型表
* date: 2022/4/20 11:10 上午
*
* @author andyliu
* @qq 115176513
* @since JDK 1.8
*/
@Data
// 声明当前是一个实体类
@Entity
// 声明当前实体类需要和数据库中哪个表进行映射
// name需要对应的表的名称
@Table(name = "sys_user1")
public class User {
@Id
// 声明主键的策略
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
// 声明属性和表字段的映射关系
// 注解写在属性上或属性的setter方法上,name指当前属性需要
// 映射到tABLE定义的表中的哪个字段上
@Column(name="user_name")
private String userName;
@Column(name="pwd")
private String pwd;
@Column(name="real_name")
private String realName;
@Column(name="dept_id")
private Integer deptId;
@Column(name="create_date")
private String createDate;
}
创建dao接口extends JpaRepository
父接口中包含了单表的crud
package com.sofwin.dao;
import com.sofwin.pojo.User;
import org.springframework.data.jpa.repository.JpaRepository;
/**
* ClassName: UserDao
* Description: TODO
* date: 2022/4/20 11:31 上午
*
* @author andyliu
* @qq 115176513
* @since JDK 1.8
* 泛型1:当前需要操作的实体类的类型
* 泛型2:主键的类型
*/
public interface UserDao extends JpaRepository<User,Integer> {
}
测试
package com.xx.test;
import com.xx.dao.UserDao;
import com.xx.pojo.User;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
/**
* ClassName: Test1
* Description: TODO
* date: 2022/4/20 11:26 上午
*
* @author andyliu
* @qq 115176513
* @since JDK 1.8
*/
@ExtendWith(SpringExtension.class)
@SpringBootTest
public class Test1 {
@Autowired
UserDao dao;
@Test
public void test01(){
System.out.println("test01");
}
@Test
public void test02(){
User user = new User();
user.setUserName("sofwin");
dao.save(user);
}
}
JPA api
参考文档:https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#dependencies.spring-boot
crudRepository
public interface CrudRepository<T, ID> extends Repository<T, ID> {
<S extends T> S save(S entity); 1
Optional<T> findById(ID primaryKey); 2
Iterable<T> findAll(); 3
long count(); 4
void delete(T entity); 5
boolean existsById(ID primaryKey); 6
void deleteById(ID id); 7
void deleteAllById(Iterable<? extends ID> ids); 8
void deleteAll(Iterable<? extends T> entities); 9
void deleteAll(); 10
Iterable<T> findAllById(Iterable<ID> ids); 11
// … more functionality omitted.
}
1.Saves the given entity.
保存给定的实体(新增、更新)
如果给定的对象没有主键值,调用insert语句,如果有主键值调用Update语句
2.Returns the entity identified by the given ID.
根据给定的主键的值获取实体
3. Returns all entities.
没有条件查询所有
4. Returns the number of entities.
查询数据库中的总数
5.Deletes the given entity.
删除给定的实体,实体必须有主键值
6.Indicates whether an entity with the given ID exists.
给定的id是否存在
7. 根据id删除
8. 根据id批量删除
9. 根据实体中的id批量删除
10. 全部删除
11. 根据多个id查询 采用in子句
save
@Test
public void testSave(){
// Saves the given entity.
Student student = new Student();
student.setAge(110);
student.setSex(11);
student.setId(1);
student.setRealName("admin1");
student.setDescription("描述1");
Student t2 = dao.save(student);
System.out.println(t2);
}
FindById
@Test
public void testFindById(){
Optional<Student> optional = dao.findById(1);
Student student = optional.get();
System.out.println(student);
}
findAll
@Test
public void testFindAll(){
List<Student> all = dao.findAll();
System.out.println(all);
}
count
@Test
public void testCound(){
long count = dao.count();
System.out.println(count);
}
delete
@Test
public void testDelete(){
Student student = new Student();
student.setId(1);
student.setAge(11);
dao.delete(student);
}
existsById
@Test
public void testExistsById(){
boolean b = dao.existsById(1);
System.out.println(b);
boolean b1 = dao.existsById(2);
System.out.println(b1);
}
PagingAndSortingRepository
public interface PagingAndSortingRepository<T, ID> extends CrudRepository<T, ID> {
Iterable<T> findAll(Sort sort); 1
Page<T> findAll(Pageable pageable); 2
1. 对所有数据进行排序
2. 对所有数据进行分页
}
@Test
public void testPaging(){
// 需要传递当前页码和每页大小
Page<Student> page = dao.findAll(PageRequest.of(1, 5));
List<Student> content = page.getContent();
System.out.println(content);
}
@Test
public void testSort(){
// 降序排列
List<Student> students = dao.findAll(Sort.by("id").descending());
for (Student st:students
) {
System.out.println(st);
}
}
方法名派生查询
package com.xx.dao;
import com.xx.pojo.Student;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
/**
* @packageName: com.sofwin.dao
* @user: andyliu
* @date: 2023/2/2 10:07
* @email 115176513@qq.com
* @description: TODO
*/
public interface StudentDao extends JpaRepository<Student,Integer> {
List<Student> findAllByRealNameEqualsAndAgeGreaterThan(String name,Integer age);
}
自定义查询
采用的是hinbernate的hql语句
@Query("from Student s where s.id>1")
List<Student> findStudents();
@Query("from Student s where s.realName=?2 and s.age>?1")
List<Student> find(Integer age,String name);
QueryByExampleExecutor
@Test
public void test01(){
Student student = new Student();
student.setRealName("admin10");
Example<Student> of = Example.of(student);
List<Student> users = dao.findAll(of);
System.out.println(users);
}
public void test01(){
Student student = new Student();
student.setRealName("10");
student.setAge(10);
ExampleMatcher matcher = ExampleMatcher.matching()
.withMatcher("realName", ExampleMatcher.GenericPropertyMatchers.endsWith());
Example<Student> of = Example.of(student,matcher);
List<Student> users = dao.findAll(of);
System.out.println(users);
}