从零开始搭建企业管理系统(三):集成 Spring Data Jpa

news2024/11/23 15:49:47

集成 Spring Data Jpa

    • 什么是 Jpa
    • 什么是 Spring Data Jpa
    • 什么是 Hibernate
    • JPA、Spring Data Jpa、Hibernate 之间的关系
    • 集成 Spring Data Jpa
      • POM 依赖
      • 配置文件
      • UserEntity
      • 启动程序
      • Jpa 配置
      • Jpa 注解
      • UserRepository
      • UserService
      • UserServiceImpl
      • UserController
      • BaseEntity

什么是 Jpa

JPA(Java Persistence API)是 Java 标准中的一套 ORM 规范(提供了一些编程的 API 接口,具体实现由 ORM 厂商实现,如Hiernate、TopLink 、Eclipselink等都是 JPA 的具体实现),借助 JPA 技术可以通过注解或者 XML 描述【对象-关系表】之间的映射关系,并将实体对象持久化到数据库中(即Object Model与Data Model间的映射)。

什么是 Spring Data Jpa

Spring Data JPA 是在实现了 JPA 规范的基础上封装的一套 JPA 应用框架(Criteria API还是有些复杂)。虽然 ORM 框架都实现了 JPA 规范,但是在不同的 ORM 框架之间切换仍然需要编写不同的代码,而使用 Spring Data JPA 能够方便的在不同的 ORM 框架之间进行切换而不需要更改代码。Spring Data JPA 旨在通过统一 ORM 框架的访问持久层的操作,来提高开发人的效率。

Spring Data JPA 是一个 JPA 数据访问抽象。也就是说 Spring Data JPA 不是一个实现或 JPA 提供的程序,它只是一个抽象层,主要用于减少为各种持久层存储实现数据访问层所需的样板代码量。但是它还是需要 JPA 提供实现程序,其实 Spring Data JPA 底层就是使用的 Hibernate 实现。

什么是 Hibernate

Hibernate对数据库结构提供了较为完整的封装,Hibernate的O/R Mapping实现了POJO 和数据库表之间的映射,以及SQL 的自动生成和执行。往往只需定义好了POJO 到数据库表的映射关系,即可通过Hibernate 提供的方法完成持久层操作。甚至不需要对SQL 的熟练掌握, Hibernate/OJB 会根据制定的存储逻辑,自动生成对应的SQL 并调用JDBC 接口加以执行。

hibernate对 JPA 的支持,不是另提供了一套专用于 JPA 的注解。一些重要的注解如@Column, @OneToMany等,hibernate并没有提供,这说明 JPA 的注解已经是hibernate 的核心,hibernate只提供了一些补充,而不是两套注解。JPA 和hibernate都提供了的注解(例如@Entity),若 JPA 的注解够用,就直接用,若 JPA 的注解不够用,直接使用hibernate的即可。

JPA、Spring Data Jpa、Hibernate 之间的关系

533121-20160122105513781-959577889.png

集成 Spring Data Jpa

POM 依赖

<!--删掉 jdbc 依赖-->
<!--<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>-->

<!-- 添加 jpa 依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

配置文件

spring:
  jpa:
    # 控制台显示SQL
    show-sql: true
    hibernate:
      # 程序启动后自动更新或者创建数据表结构
      ddl-auto: update
    properties:
      hibernate:
        # 格式化打印 sql
        format_sql: true

UserEntity

@Data
@Entity
@Table(name = "sys_user")
public class UserEntity {

    /**
     * Id 表示为表 ID
     * GenerationType.IDENTITY 使用自增长主键
     */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    private String nickname;

    private Integer age;

    private String email;

    private String password;
    
    private String createUser;
    
    private String updateUser;
    
    private Date createTime;
    
    private Date updateTime;
}

启动程序

做完这些操作之后我们先启动程序看看情况,先给大家看看我的数据库下现在是没有任何一张表的。

在这里插入图片描述

ok,启动程序,查看一下结果,程序启动成功,但是我先日志里面打印了一段 SQL 语句。
在这里插入图片描述

很明显是一个建表语句,并且字段名和类型跟我们刚才新建的 UserEitity 一模一样,猜测是 Jpa 自动根据实体类帮我们建表了,我们查看一下数据库,果然多了一张 sys_user 表。

在这里插入图片描述

这是因为我们刚才配置了 spring.jpa.hibernate.ddl-auto=update,update 默认会根据添加了@Entity的映射实体类进行表结构的创建或更新,生产上我们应该关闭这个功能,配置为 none。

spring.jpa.hibernate.ddl-auto 配置比较重要,表示建表的策略,可选的枚举值如下:

  • create:不管表是否存在,每次启动都会重新建表(会导致数据丢失)。
  • create-drop:启动的时候创建表,程序退出(SessionFactory 关闭)的时候删除表。
  • none:不进行任何操作。
  • update:如果数据表不存在则创建,在实体对象被修改后,下次启动重新修改表结构(不会删除已经存在的数据)。
  • validate:启动的时候验证数据表的结构。

Jpa 配置

Spring Data JPA已经提供了一些独立于供应商的配置选项(例如SQL日志),Spring Boot将这些选项以及一些针对Hibernate的选项作为外部配置属性公开。

属性描述备注
spring.jpa.database要操作的目标数据库,默认自动检测可选配置
spring.jpa.database-platform要操作的目标数据库的名称,默认情况下是自动检测的可以使用"Database"枚举
spring.jpa.defer-datasource-initializationdatasource初始化延迟默认false
spring.jpa.generate-ddl启动时是否初始化数据库schema默认false
spring.jpa.show-sql是否启用SQL语句日志记录默认false
spring.jpa.mapping-resources资源映射(等价于persistence.xml中的“mapping-file”条目)
spring.jpa.open-in-viewOpenEntityManagerInViewInterceptor注册,将JPA EntityManager绑定到线程,用于整个请求处理默认true
spring.jpa.properties要在JPA提供程序上设置的其他本地属性例如:spring.jpa.properties.hibernate.connection.autocommit
spring.data.jpa.repositories.enabled是否启用JPA Repository默认true
spring.data.jpa.repositories.bootstrap-modeJPA Repository的引导模式三种模式:DEFAULT(默认), DEFERRED ,LAZY
spring.jpa.hibernate.ddl-autoDDL模式hibernate.hbm2ddl的快捷方式,当使用嵌入式数据库时,默认为create-drop,否则默认值为 none
spring.jpa.hibernate.naming.implicit-strategy全限定名的隐式命名策略例如:org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
spring.jpa.hibernate.naming.physical-strategy物理命名策略的完全限定名
spring.jpa.hibernate.use-new-id-generator-mappings是否使用Hibernate更新的IdentifierGenerator AUTO, TABLE和SEQUENCE。默认true。hibernate.id.new_generator_mappings快捷方式

Jpa 注解

看完了 Spring Boot 中对于 Jpa 的配置,我们再大致的了解一下 Jpa 提供的一些注解,后续我们需要经常用到这些注解来进行开发。

注解解释
@Entity声明类为实体或表。
@Table声明表名。
@Basic指定非约束明确的各个字段。
@Embedded指定类或它的值是一个可嵌入的类的实例的实体的属性。
@ld指定的类的属性,用于识别(一个表中的主键)。
@GeneratedValue指定如何标识属性可以被初始化,例如自动、手动、或从序列表中获得的值。
@Transient指定的属性,它是不持久的,即:该值永远不会存储在数据库中。
@Column指定持久属性栏属性。
@SequenceGenerator指定在@GeneratedValue注解中指定的属性的值。它创建了一个序列.
@TableGenerator指定在@GeneratedValue批注指定属性的值发生器。它创造了的值生成的表。
@AccessType这种类型的注释用于设置访问类型。如果设置@AccessType(FIELD),则可以直接访问变量并目不需要getter和setter,但必须为public。如果设置@AccessType(PROPERTY),通过getter和setter方法访问Entity的变量。
@JoinColumn指定一个实体组织或实体的集合。这是用在多对一和一对多关联。
@UniqueConstraint指定的字段和用于主要或辅助表的唯一约束。
@ColumnResult参考使用select-子句的SQL查询中的列名。
@ManyToMany定义了连接表之间的多对多对多的关系。
@ManyToOne定义了连接表之间的多对一的关系。
@OneToMany定义了连接表之间存在一个一对多的关系。
@OneToOne定义了连接表之间有一个一对一的关系。
@NamedQueries指定命名查询的列表。
@NamedQuery指定使用静态名称的查询。

UserRepository

要创建一个 repository 接口,你首先需要定义一个实体类专用的 repository 接口。该接口必须继承 Repository,并将其泛型设置为实体类和ID类型。

# 表示这是一个 Repository 接口
@Repository
public interface UserRepository extends JpaRepository<UserEntity, Long>, Serializable {
}

定义好了 UserRepository接口之后,我们就可以对 sys_user 表进行增删改查了,我们编写一个测试类来测试一下。

@Slf4j
@SpringBootTest
class ApplicationTests {

    @Resource
    UserRepository userRepository;

    @Test
    void saveUserTest() {
        UserEntity user = new UserEntity();
        user.setName("张三");
        user.setNickname("法外狂徒");
        user.setAge(18);
        user.setPassword("666");
        // 保存用户并返回
        UserEntity result = userRepository.save(user);
        log.info("用户添加成功:{}", result);
    }

    @Test
    void contextLoads() {
    }

}

运行程序后,程序执行成功,查看日志发现执行了一条插入语句,数据库中也是正常的存在一条数据,说明Spring Data Jpa 已经集成成功,是不是很简单,只需要定义一个 Entity 和一个 Repository,什么增删改查的方法都不用定义就可以了。那么这是为什么呢,咱们继续往下看。

在这里插入图片描述

其实就是我们集成的 JpaRepository接口中已经预定义了各种 CRUD 方法,我们只需要在集成的时候插入相应的泛型对象就可以。 JpaRepository 的泛型对象是一个实体类型和 ID 类型,他继承的接口是 ListCrudRepositoryListPagingAndSortingRepository以及 QueryByExampleExecutor 接口。

在这里插入图片描述

继续点进去 ListCrudRepository 发现继承的是 CrudRepository,他两其实是提供了同等的方法,但ListCrudRepository 返回 List,而 CrudRepository 的方法返回 Iterable

ListPagingAndSortingRepository是可以进行分页和排序操作的接口。

在这里插入图片描述

最后点进去CrudRepository发现继承的是Repository接口,他是Spring Data repository 抽象的中心接口,它把要管理的 domain 类以及 domain 类的ID类型作为泛型参数。这个接口主要是作为一个标记接口,用来捕捉工作中的类型,并帮助你发现扩展这个接口的接口。 CrudRepositoryListCrudRepository 接口为被管理的实体类提供复杂的CRUD功能。

在这里插入图片描述

repository 接口的继承关系

在这里插入图片描述

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

  // … more functionality omitted.
}

1、保存给定的实体。
2、根据ID返回实体。
3、返回所有实体。
4、返回实体数量。
5、删除给定的实体。
6、根据ID判断实体是否存在。

ok,我们接着完善一下代码,编写完整的业务逻辑吧。

UserService

public interface UserService {

    /**
     * 根据ID查询用户
     *
     * @param id 用户ID
     * @return UserEntity 用户信息
     */
    UserEntity get(Long id);

    /**
     * 查询全部用户
     *
     * @return List<UserEntity> 用户集合
     */
    List<UserEntity> lists();

    /**
     * 保存用户
     *
     * @param user 用户信息
     */
    void save(UserEntity user);

    /**
     * 修改用户
     *
     * @param user 用户信息
     */
    void update(UserEntity user);

    /**
     * 删除用户
     *
     * @param id 用户id
     */
    void delete(Long id);

    /**
     * 分页查询用户
     *
     * @param pageable 分页参数
     * @return Page<UserEntity> 分页用户
     */
    Page<UserEntity> page(Pageable pageable);

}

UserServiceImpl

@Service
public class UserServiceImpl implements UserService {

    @Resource
    private UserRepository userRepository;

    @Override
    public UserEntity get(Long id) {
        return userRepository.getReferenceById(id);
    }

    @Override
    public List<UserEntity> lists() {
        return userRepository.findAll();
    }

    @Override
    public void save(UserEntity user) {
        userRepository.save(user);
    }

    @Override
    public void update(UserEntity user) {
        userRepository.save(user);
    }

    @Override
    public void delete(Long id) {
        userRepository.deleteById(id);
    }

    @Override
    public Page<UserEntity> page(Pageable pageable) {
        return userRepository.findAll(pageable);
    }
}

UserController

@RestController
@RequestMapping("/sys/user")
public class UserController {

    @Resource
    private UserService userService;

    @GetMapping("/{id}")
    public UserEntity get(@PathVariable Long id) {
        return userService.get(id);
    }

    @GetMapping("/list")
    public List<UserEntity> lists() {
        return userService.lists();
    }

    @GetMapping("/page")
    public Page<UserEntity> page(int page, int size) {
        return userService.page(PageRequest.of(page - 1, size));
    }

    @PostMapping
    public void save(@RequestBody UserEntity user) {
        userService.save(user);
    }

    @PutMapping
    public void update(@RequestBody UserEntity user) {
        userService.update(user);
    }

    @DeleteMapping("/{id}")
    public void delete(@PathVariable Long id) {
        userService.delete(id);
    }
}

ok,启动程序,使用 postman 进行测试一下,下一节我们集成 Swagger,就可以不用 postman 测试接口了。

在这里插入图片描述

证明接口是OK滴,这些方法都是一些基础的方法,复杂的用法我们后面遇到了再说。

BaseEntity

我们编写这个 BaseEntity 的目的就是,将所有的 Entity 中共有的属性给他抽取出来,像是createUser、createTIme、updateUser以及updateTime 这些字段,同时进行一个数据的自动填充,我们在插入数据的时候就不需要关注这几个字段的值了。

1、添加@EnableJpaAuditing注解,启用jpa的审计功能

@EnableJpaAuditing
@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

2、在基础类上添加jpa实体侦听器@EntityListeners(AuditingEntityListener.class),并且在具体属性上添加@CreatedBy、@CreatedDate、@LastModifiedBy、@LastModifiedBy注解。

@Data
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public class BaseEntity {

    @CreatedBy
    @Column(name = "create_user", updatable = false)
    private String createUser;

    @LastModifiedBy
    @Column(name = "update_user")
    private String updateUser;

    @CreatedDate
    @Column(name = "create_time", updatable = false)
    private Date createTime;

    @LastModifiedDate
    @Column(name = "update_time")
    private Date updateTime;
}

3、配置jpa自动填充用户,因为jpa是不知道当前的操作用户是谁的

@Configuration
public class JpaAuditorConfig implements AuditorAware<String> {
    @Override
    public Optional<String> getCurrentAuditor() {
        // TODO 先写死,等集成了Spring Security后再获取实际用户
        return Optional.of("admin");
    }
}

4、修改 UserEntity 集成 BaseEntity

@Data
@Entity
@Table(name = "sys_user")
public class UserEntity extends BaseEntity implements Serializable {

    /**
     * Id 表示为表 ID
     * GenerationType.IDENTITY 使用自增长主键
     */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    private String nickname;

    private Integer age;

    private String email;

    private String password;
}

5、启动测试

在这里插入图片描述
在这里插入图片描述

插入成功我们,看一下数据,没得任何问题,数据填充成功,不过这个时间格式还得再调整调整。再配置文件里面添加 Jackson 的配置就行了。

spring:
  jackson:
    # 全局日期格式化
    date-format: yyyy-MM-dd HH:mm:ss
    time-zone: GMT+8

本节内容到这里就结束啦。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1297474.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

.NET Core 依赖注入 Microsoft.Extensions.DependencyInjection

文章目录 前言什么是依赖注入C# 使用依赖注入框架介绍 Microsoft.Extensions.DependencyInjectionNuget安装简单单例使用打印结果 自动装配举例自动装配测试用例打印结果自动装配执行顺序测试用例有歧义构造函数渐进式构造函数循环依赖 自动装配结论 手动装配手动注入别名注入 …

ShardingSphere数据分片之分表操作

1、概述 Apache ShardingSphere 是一款分布式的数据库生态系统&#xff0c; 可以将任意数据库转换为分布式数据库&#xff0c;并通过数据分片、弹性伸缩、加密等能力对原有数据库进行增强。 Apache ShardingSphere 设计哲学为 Database Plus&#xff0c;旨在构建异构数据库上…

L1-030:一帮一

题目描述 “一帮一学习小组”是中小学中常见的学习组织方式&#xff0c;老师把学习成绩靠前的学生跟学习成绩靠后的学生排在一组。本题就请你编写程序帮助老师自动完成这个分配工作&#xff0c;即在得到全班学生的排名后&#xff0c;在当前尚未分组的学生中&#xff0c;将名次最…

使用Postman进行自动化集成测试

1 前言 笔者在使用Node开发HTTP接口的过程中&#xff0c;发现当接口数量越来越多&#xff0c;且接口之间互相依赖时&#xff0c;接口测试流程就会变得十分繁琐&#xff0c;且容易出错。那如何才能高效且全面地对接口进行测试呢&#xff1f; 通过实践&#xff0c;笔者发现可以…

程序员的职业连续性就那么重要吗?

大家好&#xff0c;我是风筝&#xff0c;微信搜「古时的风筝」&#xff0c;更多干货 年初的时候时候一个同学跟我聊天说起最近面试的经历。说投了不少简历&#xff0c;但是面试的机会不多&#xff0c;而且有的负责照片的 HR 直接跟他说&#xff1a;“你的工作连续性不达标&…

AI专题报告:AI多模态提升商业化价值,应用多点开花验证景气度

今天分享的AI系列深度研究报告&#xff1a;《AI专题报告&#xff1a;AI多模态提升商业化价值&#xff0c;应用多点开花验证景气度》。 &#xff08;报告出品方&#xff1a;太平洋证券&#xff09; 报告共计&#xff1a;21页 1 一周行情回顾 上周上证综指、深证成指、创业板指…

两个月软考-高项上岸

文章目录 前言结缘软考功亏一篑有始有终2个月计划资料部分计划截图 总结 前言 我们看小说或者电视剧电影都会看到这样的情节&#xff0c;主角一开始锦衣玉食&#xff0c;突然家道中落&#xff0c;啥都没了&#xff0c;主角再一路奋起重新找回了属于自己的一切&#xff1b;还有…

视频汇聚/音视频流媒体视频平台/视频监控EasyCVR分享页面无法播放,该如何解决?

国标GB28181安防视频监控/视频集中存储/云存储EasyCVR平台可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。平台既具备传统…

数据库系统概论期末经典大题讲解(范式提升、求闭包、求主码)

上一次我们介绍了数据库中关系代数查询&#xff0c;从选择、投影到连接等操作符&#xff0c;探索了数据库查询 大家可以移步我的文章&#xff1a;数据库系统概论期末经典大题讲解&#xff08;用关系代数进行查询&#xff09;-CSDN博客 今天&#xff0c;我们将继续沿着数据库系统…

111.am40刷机折腾记4-firefly镜像-dp正常显示

1. 平台&#xff1a; rk3399 am40 4g32g 2. 内核&#xff1a;firefly的内核&#xff08;整体镜像&#xff09; 版本&#xff1a; linux4.4.194 3. 交叉编译工具 &#xff1a;暂时不编译 4. 宿主机&#xff1a;ubuntu18.04 5. 需要的素材和资料&#xff1a;boot-am40-202…

14、SQL注入——HTTP文件头注入

文章目录 一、HTTP Header概述1.1 HTTP工作原理1.2 HTTP报文类型1.3 较重要的HTTP Header内容 二、HTTP Header注入2.1 HTTP Header注入的前提条件2.2 常见的HTTP Header注入类型 一、HTTP Header概述 1.1 HTTP工作原理 1.2 HTTP报文类型 &#xff08;1&#xff09;请求报文 …

CrystalDiskInfo中文版(硬盘检测工具) v9.1.1.0 绿色汉化版-供大家学习研究参考

更新内容 重新支持三星SATA SSD寿命报告 增加对ZHITAI SC001的支持 新增SK hynix Gold S31支持 增加了KLEVV NEO N610的支持。 改进的Micron/Crucial SATA SSD支持 已更改 卸载程序将显示一个确认对话框&#xff0c;用于删除设置。 强大功能 1.拥有多国语言&#xff0c;…

element中el-select多选v-model是对象数组

文章目录 一、问题二、解决三、最后 一、问题 element中的el-select的v-model一般都是字符串或者字符串数组&#xff0c;但是有些时候后端接口要求该字段要传对象或者对象数组&#xff0c;如果再转换一次数据&#xff0c;对于保存配置和回显都是吃力不讨好的事情。如下所示&am…

Linux--学习记录(2)

解压命令&#xff1a; gzip命令&#xff1a; 参数&#xff1a; -k&#xff1a;待压缩的文件会保留下来&#xff0c;生成一个新的压缩文件-d&#xff1a;解压压缩文件语法&#xff1a; gzip -k pathname(待压缩的文件夹名)gzip -kd name.gz&#xff08;待解压的压缩包名&#x…

数据库版本管理框架-Flyway(从入门到精通)

一、flyway简介 Flyway是一个简单开源数据库版本控制器&#xff08;约定大于配置&#xff09;&#xff0c;主要提供migrate、clean、info、validate、baseline、repair等命令。它支持SQL&#xff08;PL/SQL、T-SQL&#xff09;方式和Java方式&#xff0c;支持命令行客户端等&am…

SpringIOC之@Configuration

博主介绍&#xff1a;✌全网粉丝5W&#xff0c;全栈开发工程师&#xff0c;从事多年软件开发&#xff0c;在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战&#xff0c;博主也曾写过优秀论文&#xff0c;查重率极低&#xff0c;在这方面有丰富的经验…

手机的隐私空间的相关知识

一、删除: 进入隐私空间: 打开手机的设置,找到隐私空间(或类似名称)选项,然后输入密码或验证方式进入隐私空间。浏览内容: 在隐私空间中,您可以浏览存储在其中的照片、视频、文件等内容。选择删除: 选择您想要删除的内容,通常可以通过长按或选中复选框的方式进行多选…

孩子都能学会的FPGA:第二十六课——用FPGA实现CIC抽取滤波器

&#xff08;原创声明&#xff1a;该文是作者的原创&#xff0c;面向对象是FPGA入门者&#xff0c;后续会有进阶的高级教程。宗旨是让每个想做FPGA的人轻松入门&#xff0c;作者不光让大家知其然&#xff0c;还要让大家知其所以然&#xff01;每个工程作者都搭建了全自动化的仿…