当前位置:

首页 > 编程开发 > SpringBoot JPA常用注解如何使用

SpringBoot JPA常用注解如何使用

1.简介Jpa是一套ORM的规范hibernate不就是一个ORM框架也提供了对于JPA的实现JPA(JavaPersistenceAPI):java持久化API2.常用注解2.1@Entity标注当前类为实体类,将映射到指定的数据库表中@EntitypublicclassUsers{}2.2@Table一般与@Entity注解一起使用,如果数据库表名和类名一致时不使用@Table注解也是可以的,否则需要使用@Table注解来指定表名@Entity@Table(name="t_users")publicc

    1. 简介

    Jpa 是一套ORM 的规范
    hibernate 不就是一个 ORM 框架也提供了对于 JPA 的实现

    JPA(Java Persistence API):java 持久化 API

    2. 常用注解

    2.1 @Entity

    标注当前类为实体类,将映射到指定的数据库表中

    @Entity
    public class Users {
    		
    }

    2.2 @Table

    一般与 @Entity 注解一起使用,如果数据库表名和类名一致时不使用 @Table 注解也是可以的,
    否则需要使用 @Table 注解来指定表名

    @Entity
    @Table(name="t_users")
    public class Users {
    		
    }

    2.3 @Id 、@GeneratedValue、@SequenceGenerator、@Column

    2.3.1 @Id

    用于将实体类的属性映射为主键

    2.3.2 @GeneratedValue

    指定主键生成策略

    package javax.persistence;
    /**
     * 策略类型
     */
    public enum GenerationType {
      /**
       * 通过表产生主键,框架借由表模拟序列产生主键,使用该策略可以使应用更易于数据库移植
       */
      TABLE,
      /**
       * 通过序列产生主键,通过 @SequenceGenerator 注解指定序列名
       * MySql 不支持这种方式
       * Oracle 支持
       */
      SEQUENCE,
      /**
       * 采用数据库 ID自增长的方式来自增主键字段
       * Oracle 不支持这种方式;
       */
      IDENTITY,
      /**
       * 缺省值,JPA 根据数据库自动选择
       */
      AUTO;
    
      private GenerationType() {
      }
    }
    2.3.3 @SequenceGenerator
    2.3.4 @Column

    当实体类属性名和数据库列名不一致时必须要使用此注解

    @Entity
    @Table(name="t_users")
    public class Users {
    
      @Id
      @Column(name = "user_id")
      @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "user_seq")
      @SequenceGenerator(name = "user_seq", sequenceName = "user_seq")
      private Long userId;
    		
    }

    2.4 @Transient

    表示当前属性无需映射到数据库中

    2.5 @Temproal

    主要针对 Date 类型的属性使用,可以通过该注解指定时间的精度

    @Entity
    @Table(name="t_users")
    public class Users {
    
      @Temporal(TemporalType.DATE) 
      private Date time1;
      
      @Temporal(TemporalType.TIME)
      private Date time2;
      
      @Temporal(TemporalType.TIMESTAMP)
      private Date time3;
    }

    3. EntityManagerFactory

    类似与 hibernate 的 SessionFactory

    4. EntityManager 实体的四种状态

    新建状态: 新创建还未拥有持久性主键持久化状态: 已经拥有持久性主键并和持久化建立了上下文关系游离状态: 拥有持久性主键,但没有和持久化建立上下文关系删除状态: 拥有持久性主键,并且和持久化建立了上下文关系,但是从数据库中删除了

    4.1 find(Class entityClass, Object primaryKey)

    类似于 hibernate 中 session 的 get()

    find 如果没有查询到会返回 null

    4.2 getReference(Class entityClass, Object primaryKey)

    类似与 hibernate 中 session 的 load()
    只有当真正获取对象中的属性时,才会去执行查询的 sql 语句,getReference() 只是返回了一个代理对象

    getReference 如果没有查询到不会返回 null , 会抛出 EntityNotFoundException

    注意:使用此方法可能出现懒加载异常的情况,也就是我们还没有去获取实体类中的属性值,结果 EntityManager 就已经被关闭了

    4.3 persist

    类似与 hibernate 中 session 的 save()

    注意:执行方法时传入的对象不能为主键设置值会抛出异常

    4.4 remove

    类似与 hibernate 中 session 的 delete()

    注意:该方法只能删除持久化对象,而不能删除游离状态的对象(hibernate 可以)

    	/**
    	 * 删除游离态(失败)
    	 */
    	public void testRemove(){
    		Users user = new Users();
    		Users.setUserId(1);
    		entityManager.remove(customer);
    	}
    	
    	/**
    	 * 删除持久化状态(成功)
    	 */
    	public void testRemove(){
    		Users user = entityManager.find(Users.class, 1);
    		entityManager.remove(user);
    	}

    4.5 merge(T entity)

    类似与 hibernate 中 session 的 saveOrUpdate()

    	// 新建状态
    	public void testMerge	(){
    		Users user= new Users();
    		// 省略一系列的set
    		// user.set.....
    		Users newUser = entityManager.merge(user);
    		// user.getUserId() == null  ==> true
    		// newUser.getUserId() == null ==> false
    	}

    SpringBoot JPA常用注解如何使用

    4.6 flush()

    类似与 hibernate 中 session 的 flush()

    将上下文中所有未保存的实体保存到数据库中

    4.6 refresh()

    类似与 hibernate 中 session 的 refresh()

    刷新所有实体的属性值

    5. EntityTransaction

    EntityManager.getTransaction()

    5.1 begin

    5.2 commit

    5.3 rollback

    6. 映射关系

    6.1 单向一对多

    以用户和订单之间的关系为例,一个用户有多个订单,一个订单只属于一个用户
    对于一对多关系的 insert,无论是先插入多的一方还是一的一方都会产生额外的 update 语句,因为多的一端在 insert 时不会插入外键的列

    /**
     * 订单和用户是多对一的关系
     */
    @Entity
    @Table(name="t_order")
    public class Order {
    	// lazy为懒加载,默认为eager立即查询
    	@ManyToOne(fetch=FetchType.Lazy)
    	// @JoinColumn标注字段是一个类,userId为该类的主键
    	@JoinColumn(name="user_id")
    	private Users user;
    }

    6.2 单向多对一

    以用户和订单之间的关系为例,一个用户有多个订单,一个订单只属于一个用户
    对于多对一关系的 insert,最好先保存一的一端然后在保存多的一端。
    如果先保存多的一端再保存一的一端,为了维护外键的关系,需要对多的一端进行额外的update的操作

    /**
     * 订单和用户是多对一的关系
     */
    @Entity
    @Table(name="t_order")
    public class Order {
    	// lazy为懒加载,默认为eager立即查询
    	@ManyToOne(fetch=FetchType.Lazy)
    	// @JoinColumn标注字段是一个类,userId为该类的主键
    	@JoinColumn(name="user_id")
    	private Users user;
    }

    6.3 双向多对一

    以用户和订单之间的关系为例,一个用户有多个订单,一个订单只属于一个用户
    双向多对一就是以上两个的结合,同时使用 @OneToMany 和 @ManyToOne

    /**
     * 用户和订单是一对多的关系
     */
    @Entity
    @Table(name="t_users")
    public class User {
    	// 如果两侧都要描述关联关系的话,维护关联关系的任务要交给多的一方
    	// 使用 @OneToMany 了 mappedBy 的代表不维护关联关系,也就是不会产生额外的update语句
    	// @OneToMany 和 @JoinColumn 不能同时使用会报错
    	@OneToMany(mappedBy="user")
    	private Set orders;
    }
    
    /**
     * 订单和用户是多对一的关系
     */
    @Entity
    @Table(name="t_orders")
    public class Order {
    	// lazy为懒加载,默认为eager立即查询
    	@ManyToOne(fetch=FetchType.Lazy)
    	// @JoinColumn标注字段是一个类,userId为该类的主键
    	@JoinColumn(name="user_id")
    	private Users user;
    }

    SpringBoot JPA常用注解如何使用

    6.4 双向一对一

    以学校和校长之间的关系为例,一个学校只有一个校长,一个校长也只属于一个学校
    一方使用 @OneToMany + @JoinColumn,另一方使用 @OneToOne(mappedBy=“xx”)
    具体由哪一方维护关联关系都可以,这里我们以学校一端维护关联关系为例
    保存时先保存不维护关联关系的一方(也就是使用@OneToOne(mappedBy=“xx”)的一方),否则会产生额外的 update 语句

    /**
     * 学校
     */
    @Entity
    @Table(name="t_school")
    public class School {
    	// 默认为eager立即查询
    	@OneToOne
    	// 添加唯一约束
    	@JoinColumn(name="school_master_id", unique = true)
    	private SchoolMaster schoolMaster;
    }
    
    /**
     * 校长
     */
    @Entity
    @Table(name="t_school_master")
    public class SchoolMaster {
    	// 不维护关联关系要使用 mappedBy
    	@OneToOne(mappedBy="schoolMaster")
    	private School school;
    }

    6.5 双向多对多

    以学生和课程之间的关系为例,一个学生可以选多门课,一个课程也有多个学生,多对多需要一个中间表,也就是选课表
    维护关联关系的一方需要使用 @JoinTable
    关联关系也是只有一方维护即可,这里我们由学生表进行维护

    /**
     * 学生
     */
    @Entity
    @Table(name="t_student")
    public class Student {
    	@GeneratedValue
    	@Id
    	private Long student_id;
    	
    	// 要使用 set 集合接收
    	// 默认为lazy懒加载
    	@ManyToMany
    	// name 为中间表的表名
    	@JoinTable(name="t_student_choose_course",
    			// name 为与中间表与当前表所关联的字段的名称,referencedColumnName 为当前表中与中间表关联的字段的名称
    			joinColumns={@JoinColumn(name="student_id", referencedColumnName="student_id")},
    			// name 为与中间表与多对多另一方表所关联的字段的名称,referencedColumnName 为多对多另一方与中间表关联的字段的名称
    			inverseJoinColumns={@JoinColumn(name="course_id", referencedColumnName="course_id")})
    	private Set courses;
    }
    
    /**
     * 课程
     */
    @Entity
    @Table(name="t_course")
    public class Course {
    	@GeneratedValue
    	@Id
    	private Long course_id;
    	
    	// 要使用 set 集合接收
    	// 默认为lazy懒加载
    	@ManyToMany(mappedBy="courses")
    	private Set students;
    }

    7. 二级缓存

    开启了二级缓存之后,缓存是可以跨越 EntityManager 的,
    默认是一级缓存也就是在一个 EntityManager 中是有缓存的
    二级缓存可以实现,关闭了 EntityManager 之后缓存不会被清除
    使用 @Cacheable(true) 开启二级缓存

    8. JPQL

    8.1 查询接口

    8.1.1 createQuery
    	public void testCreateQuery(){
    		// 这里我们使用了一个 new Student,因为我们是查询 Student 中的部分属性,如果不适用 new Student 查询返回的结果就不是 Student 类型而是一个 Object[] 类型的 List
    		// 也可以在实体类中创建对应的构造器,然后使用如下这种 new Student 的方式,来把返回结果封装为Student 对象
    		String jpql = "SELECT new Student(s.name, s.age) FROM t_student s WHERE s.student_id > ?";
    		// setParameter 时下标是从1开始的
    		List result = entityManager.createQuery(jpql).setParameter(1, 1).getResultList();
    	}
    8.1.2 createNamedQuery

    需要在类上使用 @NamedQuery 注解,事先声明 sql 语句

    @NamedQuery(name="testNamedQuery", query="select * from t_student WHERE student_id = ?")
    @Entity
    @Table(name="t_student")
    public class Student {
    	@GeneratedValue
    	@Id
    	private Long student_id;
    	
    	@Column
    	private String name;
    	
    	@Column
    	private int age;
    }
    	public void testCreateNamedQuery(){
    		Query query = entityManager.createNamedQuery("testNamedQuery").setParameter(1, 3);
    		Student student = (Student) query.getSingleResult();
    	}
    8.1.3 createNativeQuery
    	public void testCreateNativeQuery(){
    		// 本地sql的意思是只能在数据库中执行的sql语句
    		String sql = "SELECT age FROM t_student WHERE student_id = ?";
    		Query query = entityManager.createNativeQuery(sql).setParameter(1, 18);
    		Object result = query.getSingleResult();
    	}

    8.2 关联查询

    存在一对多关系时,当我们查询一的一端时,默认多的一端是懒加载。此时我们如果想要一次性查询出所有的数据就需要使用关联查询

    注意: 下面 sql 中的重点就是要加上 fetch u.orders,表示要查询出用户所关联的所有订单

    	public void testLeftOuterJoinFetch(){
    		String jpql = "FROM t_users u LEFT OUTER JOIN FETCH u.orders WHERE u.id = ?";
    		
    		Users user = (Users) entityManager.createQuery(jpql).setParameter(1, 123).getSingleResult();
    	}
    本文内容来源于互联网,如有侵权请联系删除。
    作者最新文章
    编程开发
    相关文章 更多
    using namespace 使用中遇到的问题怎么解决
    using namespace 使用中遇到的问题怎么解决

    命名空间的基本概念与常见引入问题在C++等编程语言中,命名空间(namespace)是一种将代码标识符(如变量、函数、类名)封装在特定名称下的机制,其主要目的是避免命名冲突,尤其是在大型项目或使用多个第三方库时。使用“using namespace”指令可以将指定命名空间中的所有名称引入当前作用域,

    c语言函数递归 实操经验总结:这些技巧很实用
    c语言函数递归 实操经验总结:这些技巧很实用

    理解递归的基本原理在C语言中,递归是一种函数调用自身的编程技术。要掌握它,首先需要理解其核心思想:将一个复杂的大问题,分解为一个或几个与原问题相似但规模更小的子问题,直到子问题足够简单,可以直接求解。这个过程通常包含两个关键部分:递归出口和递归体。递归出口定义了问题何时不再继续分解,即最简单、可直接

    c语言函数递归 怎么选?常见方案对比分析
    c语言函数递归 怎么选?常见方案对比分析

    递归函数的基本概念与适用场景在C语言编程中,递归是一种函数调用自身的编程技巧。它并非适用于所有问题,但在处理某些具有自相似结构的问题时,能提供极其清晰和优雅的解决方案。递归的核心思想是将一个大规模问题分解为一个或多个同类型但规模更小的子问题,直到子问题简单到可以直接求解。典型的适用场景包括树形结构的

    Objective-C 内存管理入门:从 alloc 到 dealloc 的生命周期详解
    Objective-C 内存管理入门:从 alloc 到 dealloc 的生命周期详解

    理解内存管理的基石在Objective-C的编程世界中,内存管理是开发者必须掌握的核心技能之一。它直接关系到应用的性能、稳定性与资源利用效率。与一些采用自动垃圾回收机制的语言不同,Objective-C在很长一段时间里,依赖一套基于引用计数的、需要开发者部分介入的管理规则。这套规则的核心思想是明确的

    如何正确使用 dealloc 以避免 iOS 应用中的内存泄漏
    如何正确使用 dealloc 以避免 iOS 应用中的内存泄漏

    理解 dealloc 的角色与时机在 iOS 应用开发中,内存管理是保障应用性能与稳定性的基石。dealloc 方法是 Objective-C 中对象生命周期结束时的关键回调,它标志着对象即将被系统回收内存。正确理解其触发时机至关重要:当一个对象的引用计数降为零时,运行时系统会自动调用该对象的 de

    深入理解 Objective-C 中的 dealloc 方法:内存管理核心机制
    深入理解 Objective-C 中的 dealloc 方法:内存管理核心机制

    内存管理的基石在Objective-C的世界里,内存管理是开发者必须掌握的核心技能之一。作为一门在手动引用计数(MRC)时代诞生的语言,Objective-C要求程序员对对象的生命周期有清晰的认识。dealloc方法正是这一生命周期中至关重要的终点站。它是一个实例方法,当对象的引用计数降为零时,系统

    理解 native2ascii:Java 国际化开发中的字符编码工具
    理解 native2ascii:Java 国际化开发中的字符编码工具

    native2ascii 工具的基本定位在Ja va应用程序的国际化与本地化开发过程中,处理非拉丁字符集是一个常见且关键的环节。Ja va内部使用Unicode字符集来统一表示全球各种语言的文字,但其属性文件(.properties)在历史上要求使用ASCII编码,或者更准确地说,要求非ASCII字

    如何使用 native2ascii 转换中文字符为 Unicode 转义序列
    如何使用 native2ascii 转换中文字符为 Unicode 转义序列

    理解 native2ascii 工具的基本用途在软件开发,特别是涉及国际化处理的场景中,开发者常常需要处理不同编码的文本资源。native2ascii 是 Ja va 开发工具包(JDK)中提供的一个命令行实用程序,其主要功能是将包含本地字符编码(非ASCII字符)的文件,转换为包含 Unicode

    Java native2ascii 命令详解:解决属性文件乱码问题
    Java native2ascii 命令详解:解决属性文件乱码问题

    native2ascii 命令的由来与作用在Ja va开发中,处理国际化资源文件是一个常见需求。资源文件通常以.properties格式存储,用于支持多语言界面。然而,Ja va属性文件默认采用ISO-8859-1字符集编码,这导致了一个直接的问题:当文件中包含非拉丁字符(如中文、日文、韩文等)时,

    一个 memwatch 实战案例:定位野指针问题
    一个 memwatch 实战案例:定位野指针问题

    内存监控工具的价值与挑战在软件开发,尤其是使用C/C++这类手动管理内存的语言时,内存错误是程序员最常遭遇的难题之一。其中,野指针问题因其隐蔽性和破坏性,往往成为最难定位的“幽灵”缺陷。它可能潜伏在代码中,在特定条件下才被触发,导致程序崩溃、数据损坏或难以预测的行为。传统的调试手段,如打印日志或使用

    查看更多
    精品专题 更多
    装机必备
    装机必备

    正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

    Windows
    Windows

    正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

    macOS软件
    macOS软件

    正软商城macOS软件专区,精选适用于Mac电脑的办公、设计、影音、效率、开发和系统工具,提供软件功能介绍、macOS兼容版本、正版授权及购买下载服务。

    Mac软件 更多
    灵活计算器
    灵活计算器
    macOS/iOS/Android

    灵活计算器是一款笔记式算数应用,支持实时计算、动态关联和云端同步功能。记录、整理和输出之间的过渡会更自然,适合长期写作、做笔记或持续沉淀个人内容。

    赤友清理大师
    赤友清理大师
    macOS

    赤友清理大师是一款为 Mac 设计的智能清理优化工具,可精准扫描垃圾、大文件、重复文件等,释放磁盘空间。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

    极度公式
    极度公式
    Windows/macOS/Linux

    极度公式是一款跨平台专业LaTeX公式识别编辑软件,支持OCR公式识别和多平台编辑。和使用说明,避免使用,享受完整功能与稳定支持。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

    WINDOWS 更多
    Windows 10
    Windows 10
    Windows

    Windows 10 是一款微软推出的经典操作系统,拥有硬件兼容性与多任务处理能力。它更偏向把系统状态查看和常用调节动作放在一起,适合需要持续观察和微调设备状态的场景。

    极度公式
    极度公式
    Windows/macOS/Linux

    极度公式是一款跨平台专业LaTeX公式识别编辑软件,支持OCR公式识别和多平台编辑。和使用说明,避免使用,享受完整功能与稳定支持。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

    密码键盘
    密码键盘
    Windows/macOS/iOS/Android

    密码键盘是一款兼具安全性与便捷性的高效密码管理器。日常使用里的持续防护和信息管理会更突出,适合把安全控制放进长期使用流程中的场景。