Hibernate各種基本註解及一對一(多)關係對映採坑筆記
阿新 • • 發佈:2019-01-25
- hibernate提供兩種方式配置關係對映,一種XMl配置,一種註解。SpringBoot已經自帶了hibernate註解方式,我也是特別喜歡使用註解,特此記下常用的知識點。
1.基本註解
@Table(name = " ",catalog=" ", schema=" ")
//name表名,雖然可選,建議寫上。catalog在MySql不支援,不必寫。schema在MySql中指資料庫名。
@Table(uniqueConstraints = {@UniqueConstraint(columnNames="name")})
或
@Column(name = "name" ,unique = true)
//指定建表時需要建唯一約束的列(使除主鍵外的列保持唯一約束)
@Embeddable
//表示一個非Entity類嵌入到一個Entity類作為屬性而存在。
//使用方法,新建一個類註上該註解即可。在此類同樣可使用註解對欄位進行約束。
@embedded
//該註解是用來註釋屬性的,表示該類為嵌入類,同時,該類也得註釋@Embeddable註解
@GeneratedValue(strategy=GenerationType)
GenerationType.AUTO //預設,根據底層資料庫自動選擇
GenerationType.INDENTITY //根據資料庫的Identity欄位生成
GenerationType.SEQUENCE //根據sequenqe來決定主鍵的取值
GenerationType.TABLE //使用指定表來決定主鍵取值,結合TableGenerator使用
@Id //自定義主鍵生成策略
@GeneratedValue(generator="sid") //名字
@GenericGenerator(name="sid",strategy="assigned") //策略
@EmbeddedId
//使用嵌入式主鍵類實現複合主鍵
//主鍵類必須實現Serializable介面,必須有預設的public無參構造方法,
//必須覆蓋equals和hashCode()方法,必須註解@Embeddable
//使用時,把主鍵類物件當做引數傳入Table類,對Table類進行儲存即可。
@Transient
//表示該屬性並非是到資料庫表的欄位的對映,否則預設註解@Basic
@Column(columnDefinition="TEXT", nullable=true)
//表示該欄位為資料庫中的TEXT型別,儲存長文字
關係對映註解@OneToOne(cascade = {CascadeType.ALL})
- CascadeType.PERSIST:級聯新增(又稱級聯儲存):對order物件儲存時也對items裡的物件也會儲存。對應EntityManager的presist方法。
- CascadeType.MERGE:級聯合並(級聯更新):若items屬性修改了那麼order物件儲存時同時修改items裡的物件。對應EntityManager的merge方法 。
- CascadeType.REMOVE:級聯刪除:對order物件刪除也對items裡的物件也會刪除。對應EntityManager的remove方法。
- CascadeType.REFRESH:級聯重新整理:獲取order物件裡也同時也重新獲取最新的items時的物件。對應EntityManager的refresh(object)方法有效。即會重新查詢資料庫裡的最新資料。
- CascadeType.ALL:以上四種都是。
2.級聯儲存異常
org.springframework.dao.InvalidDataAccessApiUsageException: detached entity passed to persist
解決方法:
在進行多對多(一)儲存操作時,資料表定義主鍵為自增,但在執行插入前需設定ID為-1。有多個級聯關係,每個物件都要進行設定。即可避免該異常。如下:
public void test() {
User user=new User();
user.setId(-1); //加上這一句即可!!!
user.setUsername("李彤");
user.setPassword("1144");
user.setRoles(roles);
}
級聯查詢異常
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of .... could not initialize proxy -
- 翻譯過來就是Hibernate無法延遲載入,該異常多出現在一對多查詢時,解決方法:
@OneToMany(cascade={CascadeType.ALL}, fetch=FetchType.LAZY)
Lazy
:延遲載入該關聯物件,改為EAGER
即可。
下面講關係對映,務必牢記:
級聯儲存\刪除時取決於Entity類中cascade = {xxx}註解。
若是cascade = {CascadeType.ALL},直接delete主表物件即可級聯刪除屬性物件
3.一對一
(1)單向
@Entity
@Table(name="User")
public class User {
@Id
@GeneratedValue
@Column(name="sid")
private int sid;
@Column(name="name")
private String name;
@OneToOne(cascade = {CascadeType.ALL})
@JoinColumn(name = "pid",unique=true)
//name=定義外來鍵在本表的欄位名,若只配置本類,則為單向關聯
//unique=true是指這個欄位的值在這張表裡不能重複,所有記錄值都要唯一,就像主鍵那樣
private Room room;
public User() {
super();
// 多對一
}
...
}
(2)雙向
@Entity
@Table(name="Room")
public class Room {
@Id
@Column(name="cid")
private int cid;
@Column(name="addr")
private String addr;
@OneToOne(mappedBy="room")//被控方
//mappedBy同樣指定由對方來進行維護關聯關係
private User user;
public Room() {
super();
// 多對一
}
...
}
4.一對多單向
@Entity
@Table(name="Room")
public class Room {
@Id
@GeneratedValue
@Column(name="cid")
private int cid;
@Column(name="addr")
private String addr;
@OneToMany(cascade={CascadeType.ALL}, fetch=FetchType.LAZY) //一對多為Lazy,多對一為Eager
@JoinColumn(name="cid") //name=定義外來鍵在本表的欄位名 rCN=關聯外來鍵物件的哪個欄位
private Set<User> users;
public Room() {
super();
// 一對多:一方持有多方的引用
}
...
}
//正常建表
@Entity
@Table(name="User")
public class User {
@Id
@GeneratedValue
@Column(name="sid")
private int sid;
@Column(name="name")
private String name;
public User() {
super();
//一對多
}
...
}
5.多對一單向
@Entity
@Table(name="User")
public class User {
@Id
@GeneratedValue
@Column(name="sid")
private int sid;
@Column(name="name")
private String name;
@ManyToOne(cascade={CascadeType.ALL}, fetch=FetchType.EAGER) //一對多為Lazy,多對一為Eager
@JoinColumn(name="cid", referencedColumnName="cid") //name=定義外來鍵在本表的欄位名 rCN=關聯外來鍵物件的哪個欄位
private Room room;
public User() {
super();
// 多對一
}
...
}
//正常建表
@Entity
@Table(name="Room")
public class Room {
@Id
@Column(name="cid")
private int cid;
@Column(name="addr")
private String addr;
public Room() {
super();
// 多對一
}
...
}
6.一對多(多對一)雙向
@Entity
@Table(name="User")
public class User {
@Id
@GeneratedValue
@Column(name="sid")
private int sid;
@Column(name="name")
private String name;
@ManyToOne(cascade={CascadeType.ALL}, fetch=FetchType.EAGER) //一對多為Lazy,多對一為Eager
@JoinColumn(name="cid") //name=定義外來鍵在本表的欄位名
private Room room;
public User() {
super();
// 多對一
}
...
}
@Entity
@Table(name="Room")
public class Room {
@Id
@GeneratedValue
@Column(name="cid")
private int cid;
@Column(name="addr")
private String addr;
@OneToMany(cascade={CascadeType.ALL}, fetch=FetchType.LAZY) //一對多為Lazy,多對一為Eager
@JoinColumn(name="cid") //name=定義外來鍵在本表的欄位名
private Set<User> users;
public Room() {
super();
// 一對多:一方持有多方的引用
}
...
}
7.多對多
(1)單向
@Entity
@Table(name="t_course")
public class Course
{
@Id
@GeneratedValue
private int id;
private String name;
@ManyToMany ---> ManyToMany指定多對多的關聯關係
@JoinTable(name="t_teacher_course",
joinColumns={@JoinColumn(name="cid")},
inverseJoinColumns={ @JoinColumn(name = "tid") })
/*因為多對多之間會通過一張中間表來維護兩表直接的關係,所以通過 JoinTable
這個註解來宣告,我方是Course,所以在對方外來鍵的名稱就是 rid,
inverseJoinColumns也是一個 @JoinColumn型別的陣列,
表示的是對方在我這放中的外來鍵名稱,對方是Teacher,所以在我方外來鍵的名稱就是 tid*/
private Set<Teacher> teachers;
...
}
(2)雙向
@Entity
@Table(name="t_teacher")
public class Teacher
{
@Id
@GeneratedValue
private String name;
@ManyToMany(mappedBy="teachers")//表示由Course那一方來進行維護
private Set<Course> courses;
...
}