1. 程式人生 > >Hibernate各種基本註解及一對一(多)關係對映採坑筆記

Hibernate各種基本註解及一對一(多)關係對映採坑筆記

  • 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;
    ...

}