Spring Data JPA实现数据的增删改查操作
https://blog.csdn.net/pan_junbiao/article/details/105245983
1、JPA(Java持久层API)
1.1 认识Spring Data
Spring Data 是Spring的一个子项目,旨在统一和简化各类型数据的持久化存储方式,而不拘泥于是关系型数据库还是NoSQL数据库。无论是哪种持久化存储方式,数据访问对象(Data Access Objects,DAO)都会提供对对象的增加、删除、修改和查询的方法,以及排序和分页方法等。
Spring Data 提供了基于这些层面的统一接口(如:CrudRepository、 PagingAndSortingRepository),以实现持久化的存储。
1.2 认识JPA
JPA(Java Persistence API)是Java的持久化API,用于对象的持久化。它是一个非常强大的ORM持久化的解决方案,免去了使用JDBCTemplate开发的编写脚本工作。JPA通过简单约定好接口方法的规则自动生成相应的JPQL语句,然后映射成POJO对象。
JPA是一个规范化接口,封装了Hibernate的操作作为默认实现,让用户不通过任何配置即可完成数据库的操作。
2、认识JPA的接口
JPA提供了操作数据库的接口。在开发过程中继承和使用这些接口,可简化现有的持久化开发工作。可以使Spring找到自定义接口,并生成代理类,后续可以把自定义接口注入Spring容器中进行管理。在自定义接口过程中,可以不写相关的SQL操作,由代理类自动生成。
2.1 JPA接口JpaRepository
JpaRepository接口继承自PagingAndSortingRepository接口。该接口提供了JPA的相关实用功能,以及通过Example进行查询的功能。Example对象是JPA提供用来构造查询条件的对象。该接口的关键代码如下:
- public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T>
- {
- }
在上述代码中,T 表示实体对象,ID 表示主键。ID必须实现序列号。
JpaRepository接口的源代码如下:
- @NoRepositoryBean
- public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T>
- {
- List<T> findAll();
-
- List<T> findAll(Sort var1);
-
- List<T> findAllById(Iterable<ID> var1);
-
- <S extends T> List<S> saveAll(Iterable<S> var1);
-
- void flush();
-
- <S extends T> S saveAndFlush(S var1);
-
- void deleteInBatch(Iterable<T> var1);
-
- void deleteAllInBatch();
-
- T getOne(ID var1);
-
- <S extends T> List<S> findAll(Example<S> var1);
-
- <S extends T> List<S> findAll(Example<S> var1, Sort var2);
- }
JpaRepository接口提供的方法与说明:
方法 | 描述 |
---|---|
List<T> findAll(); | 查找所有实体。 |
List<T> findAll(Sort var1); | 排序、查找所有实体。 |
List<T> findAllById(Iterable<ID> var1); | 返回制定一组ID的实体。 |
<S extends T> List<S> saveAll(Iterable<S> var1); | 保存集合。 |
void flush(); | 执行缓存与数据库同步。 |
<S extends T> S saveAndFlush(S var1); | 强制执行持久化。 |
void deleteInBatch(Iterable<T> var1); | 删除一个实体集合。 |
void deleteAllInBatch(); | 删除所有实体。 |
T getOne(ID var1); | 返回ID对应的实体。如果不存在,则返回空值。 |
<S extends T> List<S> findAll(Example<S> var1); | 查询满足Example的所有对象。 |
<S extends T> List<S> findAll(Example<S> var1, Sort var2); | 查询满足Example的所有对象,并且进行排序返回。 |
2.2 数据操作接口CrudRepository
CrudRepository接口继承自Repository接口,并新增了增加、删除、修改和查询方法。
CrudRepository接口的源代码如下:
- @NoRepositoryBean
- public interface CrudRepository<T, ID> extends Repository<T, ID>
- {
- <S extends T> S save(S var1);
-
- <S extends T> Iterable<S> saveAll(Iterable<S> var1);
-
- Optional<T> findById(ID var1);
-
- boolean existsById(ID var1);
-
- Iterable<T> findAll();
-
- Iterable<T> findAllById(Iterable<ID> var1);
-
- long count();
-
- void deleteById(ID var1);
-
- void delete(T var1);
-
- void deleteAll(Iterable<? extends T> var1);
-
- void deleteAll();
- }
CrudRepository接口提供的方法与说明:
方法 | 说明 |
---|---|
<S extends T> S save(S var1); | 保存实体。当实体中包含主键时,JPA会进行更新操作。 |
<S extends T> Iterable<S> saveAll(Iterable<S> var1); | 保存所有实体。实体必须不为空。 |
Optional<T> findById(ID var1); | 根据主键ID检索实体。 |
boolean existsById(ID var1); | 根据主键ID检索实体,返回是否存在。值为布尔类型。 |
Iterable<T> findAll(); | 返回所有实体。 |
Iterable<T> findAllById(Iterable<ID> var1); | 根据给定的一组ID值返回一组实体。 |
long count(); | 返回实体的数量 |
void deleteById(ID var1); | 根据ID删除数据。 |
void delete(T var1); | 删除给定的实体。 |
void deleteAll(Iterable<? extends T> var1); | 删除实体。 |
void deleteAll(); | 删除所有实体。 |
3、使用JPA实现数据的增删改查操作
【实例】创建SpringBoot项目,使用JPA实现数据的增删改查操作。
3.1 创建数据库表
使用MySQL数据库,创建 tb_user 用户信息数据表,并添加测试数据。
- -- 判断数据表是否存在,存在则删除
- DROP TABLE IF EXISTS tb_user;
-
- -- 创建“用户信息”数据表
- CREATE TABLE IF NOT EXISTS tb_user
- (
- user_id INT AUTO_INCREMENT PRIMARY KEY COMMENT '用户编号',
- user_name VARCHAR(50) NOT NULL COMMENT '用户姓名',
- blog_url VARCHAR(50) NOT NULL COMMENT '博客地址',
- remark VARCHAR(50) COMMENT '备注'
- ) COMMENT = '用户信息表';
-
- -- 添加数据
- INSERT INTO tb_user(user_name,blog_url,remark) VALUES('pan_junbiao的博客','https://blog.csdn.net/pan_junbiao','您好,欢迎访问 pan_junbiao的博客');
- INSERT INTO tb_user(user_name,blog_url,remark) VALUES('pan_junbiao的博客_02','https://blog.csdn.net/pan_junbiao','您好,欢迎访问 pan_junbiao的博客');
执行结果:
3.2 创建项目并配置JPA环境
(1)创建SpringBoot项目
创建SpringBoot项目,并创建项目结构:dao(数据访问层)、service(服务层)、entity(实体层),如下图:
(2)添加JPA和MySQL数据库的依赖
在pom.xml配置文件中,添加如下依赖:
- <!-- Spring Data JPA -->
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-data-jpa</artifactId>
- </dependency>
-
- <!-- MySQL的JDBC数据库驱动 -->
- <dependency>
- <groupId>mysql</groupId>
- <artifactId>mysql-connector-java</artifactId>
- <version>8.0.19</version>
- </dependency>
(3)配置数据库连接信息
SpringBoot项目使用MySQL等关系型数据库,需要配置连接信息。
将默认的application.properties文件的后缀修改为“.yml”,即配置文件名称为:application.yml,并配置以下MySQL数据库的连接信息:
- spring:
- datasource:
- url: jdbc:mysql://localhost:3306/db_admin?useSSL=false&
- username: root
- password: 123456
- driver-class-name: com.mysql.cj.jdbc.Driver
- jpa:
- database: MYSQL
- show-sql: true
- open-in-view: true
- properties:
- hibernate:
- enable_lazy_load_no_trans: true
- dialect: org.hibernate.dialect.MySQL5Dialect
- ddl-auto: update
3.3 实现增删改查代码
(1)实体层(Entity层)
在实体层(Entity层)中,创建UserInfo.java(用户信息实体类)。
- package com.pjb.jpauserdemo.entity;
-
- import javax.persistence.*;
-
- /**
- * 用户信息实体类
- * @author pan_junbiao
- **/
- @Entity
- @Table(name = "tb_user")
- public class UserInfo
- {
- //用户ID
- @Id
- @GeneratedValue(strategy = GenerationType.IDENTITY)
- @Column(name = "user_id")
- private int userId;
-
- //用户姓名
- @Column(name = "user_name")
- private String userName;
-
- //博客地址
- @Column(name = "blog_url")
- private String blogUrl;
-
- //备注
- private String remark;
-
- //省略getter与setter方法...
- }
(2)数据库访问层(Dao层)
在数据库访问层(Dao层)中,创建UserDao.java(用户信息数据库访问接口),并继承JpaRepository接口。
- package com.pjb.jpauserdemo.dao;
-
- import com.pjb.jpauserdemo.entity.UserInfo;
- import org.springframework.data.jpa.repository.JpaRepository;
- import org.springframework.stereotype.Repository;
-
- /**
- * 用户信息数据库访问接口
- * @author pan_junbiao
- **/
- @Repository
- public interface UserDao extends JpaRepository<UserInfo,Integer>
- {
- }
(3)业务逻辑层(Service层)
在业务逻辑层(Service层)中,创建UserService.java(用户业务逻辑接口)。
- package com.pjb.jpauserdemo.service;
-
- import com.pjb.jpauserdemo.entity.UserInfo;
- import java.util.List;
-
- /**
- * 用户业务逻辑接口
- * @author pan_junbiao
- **/
- public interface UserService
- {
- /**
- * 根据用户ID,查询用户信息
- */
- public UserInfo findById(int userId);
-
- /**
- * 查询用户列表
- */
- public List<UserInfo> findAll();
-
- /**
- * 新增用户
- */
- public UserInfo save(UserInfo userInfo);
-
- /**
- * 修改用户
- */
- public UserInfo edit(UserInfo userInfo);
-
- /**
- * 删除用户
- */
- public boolean deleteById(int userId);
- }
在业务逻辑层(Service层)下,创建 impl 目录,在该目录下创建UserServiceImpl.java(用户业务逻辑类)。
- package com.pjb.jpauserdemo.service.impl;
-
- import com.pjb.jpauserdemo.dao.UserDao;
- import com.pjb.jpauserdemo.entity.UserInfo;
- import com.pjb.jpauserdemo.service.UserService;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Service;
-
- import java.util.List;
-
- /**
- * 用户业务逻辑类
- * @author pan_junbiao
- **/
- @Service
- public class UserServiceImpl implements UserService
- {
- @Autowired
- private UserDao userDao;
-
- /**
- * 根据用户ID,查询用户信息
- */
- @Override
- public UserInfo findById(int userId)
- {
- return userDao.findById(userId).get();
- }
-
- /**
- * 查询用户列表
- */
- @Override
- public List<UserInfo> findAll()
- {
- return userDao.findAll();
- }
-
- /**
- * 新增用户
- */
- @Override
- public UserInfo save(UserInfo userInfo)
- {
- return userDao.save(userInfo);
- }
-
- /**
- * 修改用户
- */
- @Override
- public UserInfo edit(UserInfo userInfo)
- {
- return userDao.save(userInfo);
- }
-
- /**
- * 删除用户
- */
- @Override
- public boolean deleteById(int userId)
- {
- boolean result = true;
- try
- {
- userDao.deleteById(userId);
- }
- catch(Exception ex)
- {
- result = false;
- }
- return result;
- }
- }
3.4 执行测试
3.4.1 查询数据
- @Autowired
- private UserService userService;
-
- /**
- * 测试:根据用户ID,查询用户信息
- * @author pan_junbiao
- */
- @Test
- public void findById()
- {
- //查询用户编号为1的用户信息
- UserInfo user = userService.findById(1);
-
- if (user != null)
- {
- //打印结果
- System.out.println("用户编号:" + user.getUserId());
- System.out.println("用户姓名:" + user.getUserName());
- System.out.println("博客地址:" + user.getBlogUrl());
- System.out.println("备注信息:" + user.getRemark());
- }
- }
执行结果:
3.4.2 查询列表
- /**
- * 测试:查询用户列表
- * @author pan_junbiao
- */
- @Test
- public void findAll()
- {
- //查询用户列表
- List<UserInfo> userList = userService.findAll();
-
- if (userList != null && userList.size() > 0)
- {
- for (UserInfo user : userList)
- {
- //打印结果
- System.out.println("用户编号:" + user.getUserId());
- System.out.println("用户姓名:" + user.getUserName());
- System.out.println("博客地址:" + user.getBlogUrl());
- System.out.println("备注信息:" + user.getRemark());
- System.out.println("===========================================");
- }
- }
- }
执行结果:
3.4.3 新增操作
- /**
- * 测试:新增用户
- * @author pan_junbiao
- */
- @Test
- public void save()
- {
- //创建新用户
- UserInfo user = new UserInfo();
- user.setUserName("pan_junbiao的博客_03");
- user.setBlogUrl("https://blog.csdn.net/pan_junbiao");
- user.setRemark("您好,欢迎访问 pan_junbiao的博客");
-
- //执行新增操作
- userService.save(user);
-
- //如果新增成功,则可以获取自增主键
- //否则新增失败,则抛出异常
- if (user.getUserId() > 0)
- {
- System.out.println("新增用户成功,新增的用户信息:");
- System.out.println("用户编号:" + user.getUserId());
- System.out.println("用户姓名:" + user.getUserName());
- System.out.println("博客地址:" + user.getBlogUrl());
- System.out.println("备注信息:" + user.getRemark());
- }
- }
执行结果:
查询数据表:
从查询的数据表结果中可以看到,成功新增了ID为3的用户信息。
3.4.4 修改操作
- /**
- * 测试:修改用户
- * @author pan_junbiao
- */
- @Test
- public void edit()
- {
- //创建修改用户
- UserInfo user = new UserInfo();
- user.setUserId(3);
- user.setUserName("pan_junbiao的博客_04");
- user.setBlogUrl("https://blog.csdn.net/pan_junbiao");
- user.setRemark("您好,欢迎访问 pan_junbiao的博客");
-
- //执行修改操作
- userService.edit(user);
-
- //如果没有抛出异常,则表示执行成功
- System.out.println("修改用户成功");
- }
查询数据表:
从查询的数据表结果中可以看到,ID为3的用户信息已被修改。
3.4.5 删除操作
- /**
- * 测试:删除用户
- * @author pan_junbiao
- */
- @Test
- public void deleteById()
- {
- //执行新增操作
- boolean result = userService.deleteById(3);
-
- //打印结果
- if (result)
- {
- System.out.println("删除用户成功");
- }
- else
- {
- System.out.println("删除用户失败");
- }
- }
查询数据表:
从查询的数据表结果中可以看到,ID为3的用户信息已被删除。
3.4.6 完整的测试代码
- package com.pjb.jpauserdemo.service.impl;
-
- import com.pjb.jpauserdemo.entity.UserInfo;
- import com.pjb.jpauserdemo.service.UserService;
- 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.SpringRunner;
-
- import java.util.List;
-
-
- /**
- * 用户信息业务逻辑测试类
- * @author pan_junbiao
- **/
- @SpringBootTest
- @RunWith(SpringRunner.class)
- public class UserServiceImplTest
- {
- @Autowired
- private UserService userService;
-
- /**
- * 测试:根据用户ID,查询用户信息
- * @author pan_junbiao
- */
- @Test
- public void findById()
- {
- //查询用户编号为1的用户信息
- UserInfo user = userService.findById(1);
-
- if (user != null)
- {
- //打印结果
- System.out.println("用户编号:" + user.getUserId());
- System.out.println("用户姓名:" + user.getUserName());
- System.out.println("博客地址:" + user.getBlogUrl());
- System.out.println("备注信息:" + user.getRemark());
- System.out.println("\n");
- }
- }
-
- /**
- * 测试:查询用户列表
- * @author pan_junbiao
- */
- @Test
- public void findAll()
- {
- //查询用户列表
- List<UserInfo> userList = userService.findAll();
-
- if (userList != null && userList.size() > 0)
- {
- for (UserInfo user : userList)
- {
- //打印结果
- System.out.println("用户编号:" + user.getUserId());
- System.out.println("用户姓名:" + user.getUserName());
- System.out.println("博客地址:" + user.getBlogUrl());
- System.out.println("备注信息:" + user.getRemark());
- System.out.println("===========================================");
- }
- }
- }
-
- /**
- * 测试:新增用户
- * @author pan_junbiao
- */
- @Test
- public void save()
- {
- //创建新用户
- UserInfo user = new UserInfo();
- user.setUserName("pan_junbiao的博客_03");
- user.setBlogUrl("https://blog.csdn.net/pan_junbiao");
- user.setRemark("您好,欢迎访问 pan_junbiao的博客");
-
- //执行新增操作
- userService.save(user);
-
- //如果新增成功,则可以获取自增主键
- //否则新增失败,则抛出异常
- if (user.getUserId() > 0)
- {
- System.out.println("新增用户成功,新增的用户信息:");
- System.out.println("用户编号:" + user.getUserId());
- System.out.println("用户姓名:" + user.getUserName());
- System.out.println("博客地址:" + user.getBlogUrl());
- System.out.println("备注信息:" + user.getRemark());
- }
- }
-
- /**
- * 测试:修改用户
- * @author pan_junbiao
- */
- @Test
- public void edit()
- {
- //创建修改用户
- UserInfo user = new UserInfo();
- user.setUserId(3);
- user.setUserName("pan_junbiao的博客_04");
- user.setBlogUrl("https://blog.csdn.net/pan_junbiao");
- user.setRemark("您好,欢迎访问 pan_junbiao的博客");
-
- //执行修改操作
- userService.edit(user);
-
- //如果没有抛出异常,则表示执行成功
- System.out.println("修改用户成功");
- }
-
- /**
- * 测试:删除用户
- * @author pan_junbiao
- */
- @Test
- public void deleteById()
- {
- //执行新增操作
- boolean result = userService.deleteById(3);
-
- //打印结果
- if (result)
- {
- System.out.println("删除用户成功");
- }
- else
- {
- System.out.println("删除用户失败");
- }
- }
- }