日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

jpa 定义中间表实体_Spring Data JPA实体详解

發布時間:2023/12/4 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 jpa 定义中间表实体_Spring Data JPA实体详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1. Spring Data JPA實體概述

JPA提供了一種簡單高效的方式來管理Java對象(POJO)到關系數據庫的映射,此類Java對象稱為JPA實體或簡稱實體。實體通常與底層數據庫中的單個關系表相關聯,每個實體的實例表示數據庫表格中的某一行。

2.?Spring Data JPA實體管理器

2.1 實體管理器概述

實體管理器(EntityManager)用于管理系統中的實體,它是實體與數據庫之間的橋梁,通過調用實體管理器的相關方法可以把實體持久化到數據庫中,同時也可以把數據庫中的記錄打包成實體對象。

2.2 實體管理器的常用方法

2.2.1 實體的四種狀態

在此之前我們要先了解實體的狀態及其轉換,見下圖

JPA實體生命周期有四種狀態

新建狀態(New):對象在保存進數據庫之前為臨時狀態。此時數據庫中沒有該對象的信息,該對象的ID屬性也為空。如果沒有被持久化,程序退出時臨時狀態的對象信息將丟失。

托管狀態(Managed):對象在保存進數據庫后或者從數據庫中加載后、并且沒有脫離Session時為持久化狀態。這時候數據庫中有對象的信息,改對象的id為數據庫中對應記錄的主鍵值。由于還在Session中,持久化狀態的對象可以執行任何有關數據庫的操作,例如獲取集合屬性的值等。

游離狀態(Datached):是對象曾經處于持久化狀態、但是現在已經離開Session了。雖然分離狀態的對象有id值,有對應的數據庫記錄,但是已經無法執行有關數據庫的操作。例如,讀取延遲加載的集合屬性,可能會拋出延遲加載異常。

刪除狀態(Removed):刪除的對象,有id值,尚且和Persistence Context有關聯,但是已經準備好從數據庫中刪除。

狀態名

作為java對象存在

在實體管理器中存在

在數據庫存在

New

Y

N

N

Managed

Y

Y

Y

Datached

N

N

N

Removed

Y

Y

N

用一段程序來示范

@Transactionalpublic voidsave(){//New 狀態

Task t = newTask();

t.setTaskName("task" + newDate().getTime());

t.setCreateTime(newDate());//Managed狀態

em.persist(t); //實體類t已經有id t.getId();

t.setTaskName("kkk"); //更新任務名稱,這時,如果提交事務,則直接將kkk更新到數據庫//Detached狀態 事務提交或者調用em.clear都直接將實體任務狀態變為Detached

em.clear();

t.setTaskName("kkk"); //更新數據不會更新到數據庫//Removed狀態

em.remove(t);

}

2.2.2??實體管理器的常用方法

對應于實體的四種狀態,實體管理器有四種常用的方法,分別是:persist / merge / clear / remove,結合狀態圖,可以判斷,對于不同狀態下的實體,各個方法操作結果會有不同:

對于不同狀態下的實體,persist 操作結果如下:

新建狀態:實體狀態遷移到托管狀態

托管狀態:實體狀態不發生改變,但會執行數據庫的insert操作

游離狀態:方法的調用將會拋出異常信息

刪除狀態:實體將重返托管狀態

對于不同狀態下的實體,merge操作結果如下:

新建狀態:系統會執行數據庫insert操作,同時返回一個托管狀態的實體

托管狀態:實體狀態不發生改變

游離狀態:系統將實體的修改保存到數據庫,同時返會一個托管狀態的實體

刪除狀態:方法調用將拋出異常

對于不同狀態下的實體,refresh 操作結果如下:

新建狀態:系統會執行數據庫insert操作,同時返回一個托管狀態的實體

托管狀態:實體狀態不發生改變,但會執行數據庫的update操作

游離狀態:實體狀態將返回托管狀態

刪除狀態:方法調用將拋出異常

對于不同狀態下的實體,remove 操作結果如下:

新建狀態:方法調用將拋出異常

托管狀態:實體狀態變成刪除狀態

分離狀態:方法調用將拋出異常

刪除狀態:不發生任何操作

2.2.3?利用實體管理器管理實體(實現實體的CURD)

public classUserRepositoryImpl {

@PersistenceContextprivateEntityManager entityManager;

@Transactionalpublic voidadd(User user) {

entityManager.persist(user);

}

@TransactionalpublicUser update(User user) {

User userUpdate= entityManager.find(User.class, user.getId());

userUpdate.setAddress(user.getAddress());

userUpdate.setName(user.getName());

userUpdate.setPhone(user.getPhone());returnuserUpdate;

}

@TransactionalpublicUser addOrUpdate(User user) {returnentityManager.merge(user);

}

@Transactionalpublic voiddelete(User user) {

entityManager.remove(user);

}publicUser findOne(Integer id) {return entityManager.find(User.class, id);

}public ListfindAll() {

String queryString= "select u from User u";

Query query=entityManager.createQuery(queryString);returnquery.getResultList();

}

}

3. Spring Data JPA實體基礎映射

3.1 表映射

@Entity //表示該類為JPA實體類

@Table(name="t_user") //對應數據庫中哪張表

public classUser {

@Column(name="phone_", length=11, nullable=true,columnDefinition="CHAR(10) default '000'") //對應數據庫表中哪個列字段及對該字段的自定義

private String phone;

3.2 主鍵映射

@Id //標明主鍵

@GeneratedValue //主鍵生成策略

@Column(name="id_")private Integer id;

更多的主鍵生成策略,詳見3.6 的總體代碼

3.3 字段映射和約束條件

@Column(name="phone_", length=11, nullable=true,columnDefinition="CHAR(10) default '000'") //對應數據庫中哪個列及對該字段的自定義

private String phone;

3.4 單實體多表格存儲

通常一個實體對應于一個表格,即表格中的所有的實體屬性都存放于一張表,如果將實體的屬性分配到多個表格存放,就涉及到單實體多表格存儲

@Entity

@Table(name="t_user",catalog="",schema="")

@SecondaryTables({//指明存放的第二張表

@SecondaryTable(name = "t_address",pkJoinColumns=@PrimaryKeyJoinColumn(name="address_id"))

})public classUser {

@Column(name="name_", length=60, nullable=false,unique=true,insertable=false)privateString name;//分表存儲

@Column(table = "t_address", name="street_", length = 100)private String street;

3.5 內嵌實體

在定義實體時可能需要將某幾個的屬性剝離出放到另外一個實體中,以使程序更有層次感,并且當其他實體也需要這幾個屬性時,我們也不需要再定義這幾個屬性,把存放這幾個屬性的實體重新引用即可,操作方法如下:

@Embeddable //標識該實體可嵌入到其他實體中

public classComment {

@Column(name="title_",length=100)

String title;

@Column(name="content_")

String content;

/*//被剝離出的屬性

@Column(name="title_",length=100)

String title;

@Column(name="content_")

String content;*/@Embedded//引入該實體

@AttributeOverrides({ //羅列出所有需要重新命名的屬性

@AttributeOverride(name = "title", column = @Column(name = "user_title")),

@AttributeOverride(name= "content", column = @Column(name = "user_content"))

})privateComment comment;

內嵌實體在數據庫中不會一點單獨的表格存放,而是跟數組實體存放于同一表格中。

3.6 實體類代碼

importjava.math.BigDecimal;importjava.util.Date;import javax.persistence.*;importorg.hibernate.annotations.GenericGenerator;

@Entity

@Table(name="t_user",catalog="",schema="")

@SecondaryTables({

@SecondaryTable(name= "t_address",pkJoinColumns=@PrimaryKeyJoinColumn(name="address_id"))

})public classUser {

@Id//標明主鍵

@GeneratedValue //主鍵生成策略

@Column(name="id_")privateInteger id;/*@Id

@GeneratedValue(generator="uuidGenerator")

@GenericGenerator(name="uuidGenerator",strategy="uuid")

@Column(name="id_",length=32)

private String id;*/

/*@Id

@GeneratedValue(strategy = GenerationType.AUTO)

@Column(name="id_")

private Integer id;*/

/**

@Id

@GeneratedValue(strategy=GenerationType.IDENTITY)

@Column(name="id_")

private Integer id;*/

/*@Id

@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "idGenerator")

@SequenceGenerator(name = "idGenerator",sequenceName="mySeq",allocationSize=1)

@Column(name="id_")

private Integer id;*/

/*@Id

@GeneratedValue(strategy = GenerationType.TABLE, generator = "userGenerator")

@TableGenerator(name = "userGenerator",table="pk_generator",

pkColumnName="gen_name",

valueColumnName="gen_value",

pkColumnValue="user_pk",

initialValue=0,

allocationSize=1)

@Column(name="id_")

private Integer id;*/@Column(name="name_", length=60, nullable=false,unique=true,insertable=false)privateString name;

@Column(name="address_", length=60, nullable=false)privateString address;

@Column(name="phone_", length=11, nullable=true,columnDefinition="CHAR(10) default '000'")privateString phone;

@Column(name="inCome_", precision=12, scale=2)privateBigDecimal inCome;

@Temporal(TemporalType.DATE)privateDate birthday;//Date 日期型,精確到年月日,例如“2008-08-08”//Time 時間型,精確到時分秒,例如“20:00:00”//Timestamp 時間戳,精確到納秒,例如“2008-08-08 20:00:00.000000001”

@Lob

@Column(name="pic_")

@Basic(fetch=FetchType.LAZY)private byte[] pic;

@Lob

@Column(name="note_")

@Basic(fetch=FetchType.LAZY)privateString note;//分表存儲

@Column(table = "t_address", name="street_", length = 100)privateString street;//分表存儲

@Column(table = "t_address", name="city_")privateString city;//分表存儲

@Column(table = "t_address", name="conutry_",length = 20)privateString conutry;

@Column(name="title_",length=100)

String title;

@Column(name="content_")

String content;/*@Embedded //引入該實體

@AttributeOverrides({ //羅列出所有需要重新命名的屬性

@AttributeOverride(name = "title", column = @Column(name = "user_title")),

@AttributeOverride(name = "content", column = @Column(name = "user_content"))

})

private Comment comment;*/

//省略get/set方法

}

4. Spring Data JPA實體高級映射

4.1 一對一實體映射的概念和實現方法

如下例,人員表(person)和地址表(adddress),person表是關系的擁有者,表中的address_id字段關聯著address表的主鍵id。

@Entitypublic classPerson {//略

@OneToOne

@JoinColumn(name="address_id",referencedColumnName="aid")//name:主表的外鍵字段; referencedColumnName:從表的主鍵//如果關聯的字段有多個,采用如下注解//@JoinColumns(value={@JoinColumn(name="address_id",referencedColumnName="aid"),@JoinColumn(name="address_id2",referencedColumnName="aid2")})

private Address address;

4.2 一對多實體映射的概念和實現方法

部門表(depart)和員工表(employee),一個部門可以有多個員工,一對多關系可以采用如下兩種實現方法。

4.2.1 中間表方式

創建中間表(depart_employee),表中存放兩個表的主鍵。通過部門id可查詢關聯員工的id,三張表存在兩個主外鍵關系。

@Entitypublic classDepart {//略

@OneToMany

@JoinTable(name= "depart_employee", //name:關聯表

joinColumns = @JoinColumn(name = "depart_id",referencedColumnName="did"), //joinColumns:關系的擁有者與關聯表的關系

inverseJoinColumns = @JoinColumn(name = "employee_id",referencedColumnName="eid"))//inverseJoinColumns:關系的被擁有者與關聯表的關系

private List employees;

4.2.2 從表增加外鍵方式

在員工表(employee2)中添加一個depart_id字段,它作為外鍵關聯部門表(depart2)的主鍵id。

@Entitypublic classDepart2 {//略

@OneToMany

@JoinColumn(name="depart_id",referencedColumnName="id")private List employee2s;

4.3 多對多實體映射的概念的實現方法

多對多的實現也是通過中間表,方法同一對多的中間表實現方式。

@Entitypublic classTeacher {//略

@ManyToMany

@JoinTable(name= "teacher_student",

joinColumns= @JoinColumn(name = "teacher_id",referencedColumnName="tid"),

inverseJoinColumns= @JoinColumn(name = "student_id",referencedColumnName="sid"))private Liststudents;

@Entitypublic classStudent {//略

@ManyToMany(mappedBy= "students")private List teachers;

4.4 級聯策略和懶加載

以@OneToOne為例,當我希望刪除人員信息時,也將其地址信息刪除,則可使用級聯策略;當我想要查詢人員信息(主實體)時,并不想同時查詢出其地址信息(子實體),可以設置懶加載。

@Entitypublic classPerson {

@OneToOne(cascade={CascadeType.REFRESH,CascadeType.REMOVE},fetch=FetchType.LAZY)//@JoinColumn(name="address_id",referencedColumnName="aid")

private Address address;

5. Spring Data JPA實體繼承

5.1 實體繼承的概念

繼承[extends]想必已不陌生,對于JPA來說,我們不但要考慮如何實現Java端的繼承關系,還要考慮如何持久化到數據庫中。JPA為此提供了三種策略,如下:

5.2 實體繼承策略

繼承關系如圖,繼承策略的注解主要應用于父類Item。

5.2.1 繼承策略之單一表策略

@Entity

@Inheritance(strategy=InheritanceType.SINGLE_TABLE)public class Item {

執行單一表策略會將所有實體的信息存放于一張表中,它的優點是信息存放于一張表,查詢效率較高,缺點是大量字段為空,浪費存儲空間。

如果類名過長或需要更改鑒別字段的名稱,可對鑒別字段及可選值自定義:

@Entity

@Inheritance(strategy=InheritanceType.SINGLE_TABLE)

@DiscriminatorColumn(name="ITYPE",discriminatorType=discriminatorType.CHAR) //聲明鑒別字段的字段名,類型

@DiscriminatorValue("I") //該表在鑒別字段列顯示的值

public class Item {

@Entity

@DiscriminatorValue("P")public class Phone extends Item {

@Entity

@DiscriminatorValue("B")public class Book extends Item {

效果如下

5.2.2 繼承策略之連接表策略

@Entity

@Inheritance(strategy=InheritanceType.JOINED)public class Item {

連接表策略會生成三張表,通過共享主鍵彼此關聯。

這種策略避免了空字段的浪費,但由于采用表關聯查詢,當數據量過大時,查詢效率較低。

5.2.3 繼承策略之每個類策略

@Entity

@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)public classItem {/*@Id

@GeneratedValue(strategy = GenerationType.AUTO)*/@Id

@GeneratedValue(strategy= GenerationType.TABLE, generator = "ItemGenerator")

@TableGenerator(name= "ItemGenerator",table="pk_generator",

pkColumnName="gen_name",

valueColumnName="gen_value",

pkColumnValue="item_pk",

initialValue=0,

allocationSize=1)private Long id;

每個類策略實際上是每個類一個表策略,這種策略要求主鍵不能使用自增的方式,如上面的代碼,采用表中獲取的方式。

三張表各自存放自己的完整信息,表之間沒有任何的關聯關系。雖然他們各自存放各自的數據,但主鍵是連續的。即三個表共用一套主鍵生成策略(三個表的主鍵都從另一個表中獲取)。

這種策略查詢效率高,同時也不存在大量空字段的浪費。

總結

以上是生活随笔為你收集整理的jpa 定义中间表实体_Spring Data JPA实体详解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。