SpringBoot JPA常用註解如何使用
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.4 remove
注意:此方法只能刪除持久化對象,而無法刪除遊離狀態的物件(hibernate 可以)
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'> /**
* 删除游离态(失败)
*/
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);
}</pre><div class="contentsignin">登入後複製</div></div>
4.5 merge(T entity)
#
// 新建状态 public void testMerge (){ Users user= new Users(); // 省略一系列的set // user.set..... Users newUser = entityManager.merge(user); // user.getUserId() == null ==> true // newUser.getUserId() == null ==> false }登入後複製
4.6 flush()
類似與hibernate 中session 的flush()將上下文中所有未儲存的實體儲存到資料庫中4.6 refresh()
類似與hibernate 中session 的refresh()刷新所有實體的屬性值##5. EntityTransaction
EntityManager.getTransaction()5.1 begin5.2 commit#5.3 rollback6. 對應關係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 單向多對一/** * 订单和用户是多对一的关系 */ @Entity @Table(name="t_order") public class Order { // lazy为懒加载,默认为eager立即查询 @ManyToOne(fetch=FetchType.Lazy) // @JoinColumn标注字段是一个类,userId为该类的主键 @JoinColumn(name="user_id") private Users user; }
如果先保存多的一端再保存一的一端,為了維護外鍵的關係,需要對多的一端進行額外的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.3 雙向多對一/** * 订单和用户是多对一的关系 */ @Entity @Table(name="t_order") public class Order { // lazy为懒加载,默认为eager立即查询 @ManyToOne(fetch=FetchType.Lazy) // @JoinColumn标注字段是一个类,userId为该类的主键 @JoinColumn(name="user_id") private Users user; }
雙向多對一就是以上兩個的結合,同時使用@OneToMany 和@ManyToOne
以使用者和訂單之間的關係為例,一個使用者有多個訂單,一個訂單只屬於一個使用者
/** * 用户和订单是一对多的关系 */ @Entity @Table(name="t_users") public class User { // 如果两侧都要描述关联关系的话,维护关联关系的任务要交给多的一方 // 使用 @OneToMany 了 mappedBy 的代表不维护关联关系,也就是不会产生额外的update语句 // @OneToMany 和 @JoinColumn 不能同时使用会报错 @OneToMany(mappedBy="user") private Set<Orders> orders; } /** * 订单和用户是多对一的关系 */ @Entity @Table(name="t_orders") public class Order { // lazy为懒加载,默认为eager立即查询 @ManyToOne(fetch=FetchType.Lazy) // @JoinColumn标注字段是一个类,userId为该类的主键 @JoinColumn(name="user_id") private Users user; }

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<Course> courses; } /** * 课程 */ @Entity @Table(name="t_course") public class Course { @GeneratedValue @Id private Long course_id; // 要使用 set 集合接收 // 默认为lazy懒加载 @ManyToMany(mappedBy="courses") private Set<Student> 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(); }
以上是SpringBoot JPA常用註解如何使用的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

熱門話題

Jasypt介紹Jasypt是一個java庫,它允許開發員以最少的努力為他/她的專案添加基本的加密功能,並且不需要對加密工作原理有深入的了解用於單向和雙向加密的高安全性、基於標準的加密技術。加密密碼,文本,數字,二進位檔案...適合整合到基於Spring的應用程式中,開放API,用於任何JCE提供者...添加如下依賴:com.github.ulisesbocchiojasypt-spring-boot-starter2. 1.1Jasypt好處保護我們的系統安全,即使程式碼洩露,也可以保證資料來源的

選擇JPA還是MyBatis取決於具體需求和偏好。 JPA和MyBatis都是Java持久層框架,都提供了將Java物件與資料庫表進行對應的功能。如果需要一個成熟的、支援跨資料庫操作的框架,或者專案已經採用了JPA作為持久層解決方案,繼續使用JPA可能是一個更好的選擇。如果要更高的效能和更靈活的SQL編寫能力,或者正在尋找一個對資料庫依賴性較小的解決方案,MyBatis更適合。

JPA和MyBatis:功能與效能比較分析引言:在Java開發中,持久化框架扮演著非常重要的角色。常見的持久化框架包括JPA(JavaPersistenceAPI)和MyBatis。本文將對這兩個框架的功能和效能進行比較分析,並提供具體的程式碼範例。一、功能對比:JPA:JPA是JavaEE的一部分,提供了一個物件導向的資料持久化解決方案。它透過註解或X

一、Redis實現分散式鎖原理為什麼需要分散式鎖在聊分散式鎖之前,有必要先解釋一下,為什麼需要分散式鎖。與分散式鎖相對就的是單機鎖,我們在寫多執行緒程式時,避免同時操作一個共享變數產生資料問題,通常會使用一把鎖來互斥以保證共享變數的正確性,其使用範圍是在同一個進程中。如果換做是多個進程,需要同時操作一個共享資源,如何互斥?現在的業務應用通常是微服務架構,這也意味著一個應用會部署多個進程,多個進程如果需要修改MySQL中的同一行記錄,為了避免操作亂序導致髒數據,此時就需要引入分佈式鎖了。想要實現分

springboot讀取文件,打成jar包後訪問不到最新開發出現一種情況,springboot打成jar包後讀取不到文件,原因是打包之後,文件的虛擬路徑是無效的,只能通過流去讀取。文件在resources下publicvoidtest(){Listnames=newArrayList();InputStreamReaderread=null;try{ClassPathResourceresource=newClassPathResource("name.txt");Input

在Springboot+Mybatis-plus不使用SQL語句進行多表添加操作我所遇到的問題準備工作在測試環境下模擬思維分解一下:創建出一個帶有參數的BrandDTO對像模擬對後台傳遞參數我所遇到的問題我們都知道,在我們使用Mybatis-plus中進行多表操作是極其困難的,如果你不使用Mybatis-plus-join這一類的工具,你只能去配置對應的Mapper.xml文件,配置又臭又長的ResultMap,然後再寫對應的sql語句,這種方法雖然看上去很麻煩,但具有很高的靈活性,可以讓我們

SpringBoot和SpringMVC都是Java開發中常用的框架,但它們之間有一些明顯的差異。本文將探究這兩個框架的特點和用途,並對它們的差異進行比較。首先,我們來了解一下SpringBoot。 SpringBoot是由Pivotal團隊開發的,它旨在簡化基於Spring框架的應用程式的建立和部署。它提供了一種快速、輕量級的方式來建立獨立的、可執行

1.自訂RedisTemplate1.1、RedisAPI預設序列化機制基於API的Redis快取實作是使用RedisTemplate範本進行資料快取操作的,這裡開啟RedisTemplate類,查看該類別的源碼資訊publicclassRedisTemplateextendsRedisAccessorimplementsRedisOperations,BeanClassLoaderAware{//聲明了value的各種序列化方式,初始值為空@NullableprivateRedisSe
