Spring Data JPA 的基本功能–CRUD 和 分页
(1)配置数据源。
(2)配置JPA相关属性,这些属性由JpaProperties类负责处理。
——上面2步都在application.properties中配置即可。
(3)使用JPA注解定义实体类。
(4)继承CrudRepository或其子接口实现DAO组件,
如要实现反应式DAO组件,继承ReactiveCrudRepository或其子接口。
我们只需要开发DAO组件的接口,并不需要提供实现类。
如果要做分页查询,需要使用Pageable参数,
但Pageable有个实现类:PageRequest,调用它的of方法即可创建 Pageable对象
HikariCP > Tomcat pooling DataSource > Commons DBCP2
Spring Boot的spring-data-starter-jdbc默认就自带了HikariCP 的JAR包。
如果你不指定任何额外信息,Spring Boot默认会为我们创建HikariCP 的数据源。
数据源的通用配置以spring.datasource.*开头的属性进行配置。
spring.datasource.*开头的属性由DataSourceProperties类负责加载、处理。
如果想对特定数据源实现增加配置,可通过特定前缀的属性进行配置,例如:
- spring.datasource.hikari.*:专门配置HikariCP的属性。
- spring.datasource.tomcat.*:专门配置Tomcat池化数据源的属性。
- spring.datasource.dbcp2.*:专门配置DBCP2数据源的属性。
@ConfigurationProperties可修饰类,将该类变成属性处理类。
@ConfigurationProperties还可修饰@Bean配置Bean组件,
此时该注解读取的配置文件中的每个属性都会调用该Bean的一个setter方法
比如在配置文件中读到一个abc属性,它就会尝试调用配置Bean的setAbc()方法
首先需要排除HikariCP依赖库,还要添加C3P0的依赖
▲ 简单配置方式,只要一行(不能定制,早期版本才支持,Spring Boot 2.4开始不再支持):
spring.datasource.type=com.mchange.v2.c3p0.ComboPooledDataSource
▲ 复杂配置(用自定义的数据源代替自动配置的数据源)
(1)先在容器中用@Bean配置一个C3P0数据源
(2)然后用@ConfigurationProperties读取配置属性来对C3P0数据源进行配置
UserServiceImpl 实现类
启动类进行测试:
因为这个项目没有添加web的jar包,所以不算是个web应用。所以直接再启动类这里进行测试
执行个有id的,且数据库有同样的id存在
执行个有id的,且数据库没有同样的id存在
#配置连接数据源,这些配置由 DataSourceProperties 类负责处理
#SpringBoot 读取到这些配置信息后,会使用 AutoConfiguration 去容器中自动配置 DataSource Bean
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/springboot?serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=123456
#配置 JPA 相关属性,由 JpaProperties 类负责处理
#SpringBoot 读取到这些配置信息后,会使用 AutoConfiguration 去容器中自动配置 EntityManagerFactory Bean
#JPA 底层就是依赖这个 EntityManagerFactory
#自动建表,只能true或者false
#spring.jpa.generate-ddl=true
#这个也是自动建表,不过比spring.jpa.generate-ddl更严谨,作用:如果已有数据表,无需创建,否则创建数据表
spring.jpa.hibernate.ddl-auto=update
#指定操作的数据库
spring.jpa.database=mysql
#是否在执行的时候显示sql语句
spring.jpa.show-sql=true
package cn.ljh.app.domain;
import lombok.Data;
import javax.persistence.*;
//添加这个注解,让这个类变成实体类
@Entity
//指定表名,表明这个实体类映射到user_inf这张表
@Table(name = "user_inf")
@Data
public class User
{
@Id
@Column(name = "user_id") // 指定列名
@GeneratedValue(strategy = GenerationType.IDENTITY)//指定主键的自动增长策略
private Integer id;
@Column(name = "user_name")
private String name;
//如果不用 @Column 指定列表,name表示列名和属性名一致
private int age;
private String password;
public User()
{
}
public User(String name, int age, String password)
{
this.name = name;
this.age = age;
this.password = password;
}
}
package cn.ljh.app.Dao;
import cn.ljh.app.domain.User;
import org.springframework.data.repository.PagingAndSortingRepository;
//CrudRepository 的第一个泛型参数是被操作的实体类型,第二个参数是实体的主键类型
public interface UserDao extends PagingAndSortingRepository<User,Integer>
{
//这个接口无需书写任何代码,只要定义一个空的接口,该接口就能完成大量、通用的 CRUD 操作。
}
package cn.ljh.app.service;
import cn.ljh.app.domain.User;
import java.util.List;
public interface UserService
{
//根据id获取一个User对象
User getUserById(Integer id);
//查询所有用户
List<User> getAllUsers();
//根据id删除用户
void deleteUserById(Integer id);
//新增和修改
void saveOrUpdateUser(User user);
//分页查询 , pageNo: 要查询哪一页的页数 , pageSize: 每页显示的条数
List<User> findUserByPage(int pageNo, int pageSize);
}
package cn.ljh.app.service.impl;
import cn.ljh.app.Dao.UserDao;
import cn.ljh.app.domain.User;
import cn.ljh.app.service.UserService;
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.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
@Service
public class UserServiceImpl implements UserService
{
private UserDao userDao;
//构造器进行依赖注入
public UserServiceImpl(UserDao userDao)
{
this.userDao = userDao;
}
//根据id获取一个User对象
@Override
public User getUserById(Integer id)
{
//findById 返回 Optional 值,可能为null
Optional<User> optional = userDao.findById(id);
//所以需要再get把数据获取出来,就不会出现null的情况
User user = optional.get();
return user;
}
//查询所有用户
@Override
public List<User> getAllUsers()
{
List<User> list = new ArrayList<>();
//findAll 方法返回 Iterable 值,可将它收集到 List 之后再返回
Iterable<User> users = userDao.findAll();
//方式1:Lambda表达式
//users.forEach(user -> list.add(user));
//方式2:Lambda表达式的简化写法----方法引用
users.forEach(list::add);
return list;
}
//根据id删除用户
@Override
public void deleteUserById(Integer id)
{
userDao.deleteById(id);
}
//新增和修改
@Override
public void saveOrUpdateUser(User user)
{
//有id就是更新,没有则是插入
userDao.save(user);
}
//分页查询 , pageNo: 要查询哪一页的页数 , pageSize: 每页显示的条数
@Override
public List<User> findUserByPage(int pageNo, int pageSize)
{
//分页对象,此处的pageNo是从0开始的,0代表第一页,所以这里的 pageNo 要 -1 。
Pageable pageable = PageRequest.of(pageNo - 1, pageSize);
//Page 包含了分页消息
Page<User> users = userDao.findAll(pageable);
//当前页数,因为pageNo-1,所以这里需要+1
int number = users.getNumber()+1;
System.err.println("总页数:" + users.getTotalPages());
System.err.println("总条数:" + users.getTotalElements());
System.err.println("当前第:" + number + " 页");
System.err.println("当前页有:" + users.getNumberOfElements() + " 条数据");
List<User> list = new ArrayList<>();
users.forEach(list::add);
return list;
}
}
package cn.ljh.app;
import cn.ljh.app.domain.User;
import cn.ljh.app.service.UserService;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import java.util.List;
@SpringBootApplication
public class App
{
public static void main(String[] args)
{
ConfigurableApplicationContext ctx = SpringApplication.run(App.class, args);
//根据类型获取bean
UserService usBean = ctx.getBean(UserService.class);
// usBean.saveOrUpdateUser(new User("小红",25,"12345"));
// usBean.saveOrUpdateUser(new User("小橙",26,"12345"));
// usBean.saveOrUpdateUser(new User("小黄",27,"12345"));
// usBean.saveOrUpdateUser(new User("小绿",28,"12345"));
// usBean.saveOrUpdateUser(new User("小青",29,"12345"));
// User user = new User("小紫", 31, "1234");
// user.setId(6);
// usBean.saveOrUpdateUser(user);
//根据id查询
// System.err.println(usBean.getUserById(2));
//查询所有
// usBean.getAllUsers().forEach(System.err::println);
// usBean.deleteUserById(6);
// usBean.getAllUsers().forEach(System.err::println);
//pageNo: 要查询哪一页的页数 , pageSize: 每页显示的条数
//分页查询:查询第2页,每页显示3条记录
List<User> userByPage = usBean.findUserByPage(3, 2);
userByPage.forEach(System.err::println);
}
}
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cn.ljh</groupId>
<artifactId>spring_data_jpa</artifactId>
<version>1.0.0</version>
<name>spring_data_jpa</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>