JPA: Java Persistence API Java 持久层 API,也就是咱们用来操作数据库的框架
首先,咱们先来捋一下 SpringBoot 如何集成 JPA 框架
1. 首先要加入 JPA 的依赖包 ?:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
2. 为了方便,我们再引入一个插件 Lombok ,有关 Lombok 的其他用法可以去百度一下 ?:
Lombok是一个Java库,能自动插入编辑器并构建工具,简化Java开发
说白了,通过这个库,在实体类上加入它设定的注解,这样咱们就可以不用写属性的 set、get 方法
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
开启 Lombok ,这个要在 idea 上安装 Lombok 插件 ?,然后应用就好了
3. 现在咱们在数据库中创建一张数据表,我的数据库名为 jpa_test, 数据表名称 t_user ?,建表语句在下面 ?
CREATE TABLE `t_user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
`username` varchar(30) NOT NULL DEFAULT '' COMMENT '用户名',
`password` varchar(50) NOT NULL DEFAULT '' COMMENT '密码',
`real_name` varchar(10) NOT NULL DEFAULT '' COMMENT '真实姓名',
`department_name` varchar(20) NOT NULL DEFAULT '' COMMENT '所在部门名称',
`create_time` datetime NOT NULL COMMENT '创建时间',
`update_time` datetime NOT NULL COMMENT '修改时间',
PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8 COMMENT='用户表';
4. 现在进行数据源的配置 ?,打开 application.properties ,填入下面 ? 的内容,根据自己的数据库信息的不同,请自行修改,不要照搬全复制!
# datasource 配置
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1/jpa_test?serverTimezone=GMT%2b8&useUnicode=yes&characterEncoding=UTF-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=123
5. 现在咱们配置一下 jpa,打开 application.properties ,填入下面 ? 的内容
# jpa 配置
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
spring.jpa.properties.hibernate.hbm2ddl.auto=validate
spring.jpa.show-sql=true
具体的配置详情信息,自行百度,我这里只是列举了一般开发所需要进行的配置
然后咱们再来一下,具体的代码编写
1. 老样子,首先要弄个实体类,创建一个 entity 包,新建一个 UserEntity 实体类 ?
package mr.s.jpa.entity;
import lombok.Data;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import javax.persistence.*;
import java.sql.Timestamp;
@Data
@Entity
@Table(name = "t_user")
@EntityListeners(AuditingEntityListener.class)
public class UserEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String password;
private String realName;
private String departmentName;
@CreatedDate
private Timestamp createTime;
@LastModifiedDate
private Timestamp updateTime;
}
画重点!!!!!!
上面的实体类中有,@CreateDate 和 @LastModifiedDate 这两个注解,这两个注解有啥用呢?为了是让我们进行插入和修改记录时,时间自动更新,这个特别方便,但是方便是方便了,我们也需要做一些其他的配置,在实体类上加入@EntityListeners(AuditingEntityListener.class) 注解,在启动类,加上 @EnableJpaAuditing 注解
2. 现在需要创建 repository 包,创建 UserRepository 接口类 ?
package mr.s.jpa.repository;
import mr.s.jpa.entity.UserEntity;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<UserEntity, Long> {
}
画重点!!!!!!
UserRepository 接口要继承 JpaRepository接口,而且要注意,JpaRepository<T, ID> T 表示实体类,ID 表示这个实体类的主键
额外知识点!!!!!!
平常我们可能会遇到主键是两个以上的字段构成的,这时候我们怎么处理呢?看下面 ?
这是两个字段组成的主键实体类 ?
@Data
@Entity
@Table(name = "t_user_role")
@EntityListeners(AuditingEntityListener.class)
@IdClass(UserRoleEntity.UserRolePrimaryKey.class)
public class UserRoleEntity {
@Id
private Integer userId;
@Id
private Integer roleId;
private String operator;
@CreatedDate
private Timestamp createTime;
@LastModifiedDate
private Timestamp updateTime;
@Data
public static class UserRolePrimaryKey implements Serializable {
private static final long serialVersionUID = -6861842133302907913L;
private Integer userId;
private Integer roleId;
}
}
这是两个字段组成主键的实体类操作接口 ?
public interface UserRoleRepository extends JpaRepository<UserRoleEntity, UserRoleEntity.UserRolePrimaryKey> {
}
准备工作都已经做完了,现在咱们开始写一些基本的增删查改吧
1. 查询(查询有很多种,下面依次讲解!)
根据主键进行查询
@Autowired
private UserRepository userRepository;
@Test
public void testGet() {
Optional<UserEntity> userEntityOptional = userRepository.findById(1L);
// 判断查询结果是否为空
if (userEntityOptional.isPresent()) {
// 获得查询结果
UserEntity userEntity = userEntityOptional.get();
System.out.println(userEntity);
}
}
根据条件进行查询,比如说根据用户名这样的查询,这种条件查询有两种解决方案
通过 Example 进行条件查询
@Autowired
private UserRepository userRepository;
@Test
public void testGet(){
UserEntity userEntity = new UserEntity();
// 设置查询条件
userEntity.setUsername("zhangsan");
Example<UserEntity> userEntityExample = Example.of(userEntity);
// 获取查询结果集合
List<UserEntity> userEntityList = userRepository.findAll(userEntityExample);
System.out.println(userEntityList.size());
// 获取单个查询结果
Optional<UserEntity> userEntityOptional = userRepository.findOne(userEntityExample);
if (userEntityOptional.isPresent()){
UserEntity saveEntity = userEntityOptional.get();
System.out.println(saveEntity);
}
}
在 UserRepository 接口写代码的方式
public interface UserRepository extends JpaRepository<UserEntity, Long> {
UserEntity findByUsername(String username);
}
@Autowired
private UserRepository userRepository;
@Test
public void testGet() {
UserEntity userEntity = userRepository.findByUsername("zhangsan");
System.out.println(userEntity);
}
在 UserRepository 接口上写原生 SQL 的方式(注意:@Param("userId") 和 SQL 语句中的 :userId 对应)
public interface UserRepository extends JpaRepository<UserEntity, Long> {
@Query(value = "select t_user.* from t_user where t_user.id = :userId", nativeQuery = true)
UserEntity findByUserId(@Param("userId") Long userId);
}
@Autowired
private UserRepository userRepository;
@Test
public void testGet() {
UserEntity userEntity = userRepository.findByUserId(1L);
System.out.println(userEntity);
}
查询排序
@Autowired
private UserRepository userRepository;
@Test
public void testGet() {
Sort sort = new Sort(Sort.Direction.ASC, "id");
List<UserEntity> userEntityList = userRepository.findAll(sort);
System.out.println(userEntityList.size());
}
分页查询
@Autowired
private UserRepository userRepository;
@Test
public void testGet() {
int page = 1;
int limit = 10;
// 注意,页号是从 0 开始的
Pageable pageable = PageRequest.of(page - 1, limit);
Page<UserEntity> userEntityPage = userRepository.findAll(pageable);
List<UserEntity> userEntityList = userEntityPage.getContent();
System.out.println(userEntityList.size());
}
2. 添加(注意要加上,@Transactional 事务注解)
@Autowired
private UserRepository userRepository;
@Transactional(rollbackFor = Exception.class)
@Test
public void testAdd() {
UserEntity userEntity = new UserEntity();
userEntity.setUsername("zhangsan");
userEntity.setPassword("123");
userEntity.setRealName("张三");
userEntity.setDepartmentName("研发部");
userRepository.saveAndFlush(userEntity);
}
3. 修改(修改和添加的区别是:修改要求实体类有主键,且主键在数据库中已经存在)
只更新不为空的字段!!!
@Autowired
private UserRepository userRepository;
@Transactional(rollbackFor = Exception.class)
@Test
public void testEdit() {
UserEntity userEntity = new UserEntity();
userEntity.setId(1L);
userEntity.setUsername("zhangsan");
userRepository.saveAndFlush(userEntity);
}
4. 删除(删除也有很多种,可以根据主键删除,可以根据条件删除,条件删除可以使用 Example 也可以在 UserRepository 接口中写对应的方法,这里只给出根据主键删除,其余的自己研究尝试一下就ok了)
@Autowired
private UserRepository userRepository;
@Transactional(rollbackFor = Exception.class)
@Test
public void testDel() {
userRepository.deleteById(1L);
}