<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                # Hibernate – 如何定義實體之間的關聯映射 > 原文: [https://howtodoinjava.com/hibernate/how-to-define-association-mappings-between-hibernate-entities/](https://howtodoinjava.com/hibernate/how-to-define-association-mappings-between-hibernate-entities/) 在上一教程中,我們了解了 [**Hiberate 實體**](//howtodoinjava.com/hibernate/hibernate-entity-persistence-lifecycle-states/ "Hibernate Entity / Persistence LifeCycle States")的四種持久狀態,并且我們注意到,只有在使用某些注解對 Java 對象進行注解時,hibernate 才能將其標識為持久對象。 否則,將它們視為與數據庫沒有直接關系的簡單普通 Java 對象。 繼續,當我們用 JPA 注解對 Java 類進行注解并使它們成為持久化實體時,我們可能會遇到兩個實體可以關聯并且必須相互引用的情況,無論是單向還是雙向。 在實際在 Hiberate 實體之間創建引用之前,讓我們了解一些基本知識。 ## 了解實體及其關聯 實體可以包含對其他實體的引用,可以直接作為嵌入式屬性或字段,也可以通過某種集合(數組,集合,列表等)間接包含對其他實體的引用。 這些關聯使用基礎表中的外鍵關系表示。 這些外鍵將依賴于參與表使用的標識符。 當一對實體中只有一個包含對另一個實體的引用時,關聯為**單向**。 如果關聯是相互的,則稱為**雙向**。 初學者在設計實體模型時的一個常見錯誤是試圖使所有關聯都是雙向的。 請記住,不是對象模型的自然組成部分的關聯不應被強加到其中。 Hibernate 查詢語言(HQL)通常被證明是在需要時訪問所需信息的更自然的方法。 理想情況下,我們希望指示僅對關系一端的更改會導致外鍵的任何更新。 實際上,Hibernate 允許我們通過將關聯的一端標記為由另一端管理來做到這一點。 **在 Hiberate 映射關聯中,一個參與類(只有一個)“管理關系”,而另一類則使用“`mappedBy`”屬性“被管理”。 我們不應該使關聯的兩端都“管理關系”。 永遠不要做。** 注意,“`mappedBy`”純粹是關于實體之間的外鍵關系如何保存的。 它與使用級聯功能保存實體本身無關。 盡管 Hibernate 讓我們指定對一個關聯的更改將導致對數據庫的更改,但是它不允許我們使對關聯的一端的更改自動反映在 Java POJO 的另一端。 為此,我們必須使用級聯功能。 ## 通過示例了解關聯 讓我們快速構建示例,以了解我們上面已閱讀的有關實體關聯的內容以及應如何完成。 在此示例中,我使用兩個簡單實體`(AccountEntity`和`EmployeeEntity`),然后在它們之間創建 [**一對一關聯**](//howtodoinjava.com/hibernate/hibernate-one-to-one-mapping-using-annotations/ "Hibernate one-to-one mapping using annotations")。 然后,我們將看到各種關聯選項如何改變運行時行為和復雜性。 **`AccountEntity.java`** ```java @Entity @Table(name = "Account") public class AccountEntity implements Serializable { private static final long serialVersionUID = 1L; @Id @Column(name = "ID", unique = true, nullable = false) @GeneratedValue(strategy = GenerationType.SEQUENCE) private Integer accountId; @Column(name = "ACC_NO", unique = false, nullable = false, length = 100) private String accountNumber; //We will define the association here EmployeeEntity employee; //Getters and Setters are not shown for brevity } ``` **`EmployeeEntity.java`** ```java @Entity @Table(name = "Employee") public class EmployeeEntity implements Serializable { private static final long serialVersionUID = -1798070786993154676L; @Id @Column(name = "ID", unique = true, nullable = false) @GeneratedValue(strategy = GenerationType.SEQUENCE) private Integer employeeId; @Column(name = "FIRST_NAME", unique = false, nullable = false, length = 100) private String firstName; @Column(name = "LAST_NAME", unique = false, nullable = false, length = 100) private String lastName; //We will define the association here AccountEntity account; //Getters and Setters are not shown for brevity } ``` #### 方案 1)由兩個實體管理的關聯 在這種類型的關聯中,我們將使用`@OneToOne`注解如下定義關聯。 ```java //Inside EmployeeEntity.java @OneToOne AccountEntity account; //Inside AccountEntity.java @OneToOne EmployeeEntity employee; ``` 通過上述關聯,兩端都在管理關聯,因此必須使用實體 java 文件中定義的設置器方法使用彼此的信息來更新雙方。 如果您未這樣做,則將無法獲取關聯的實體信息,并且該信息將作為`null`返回。 ```java public class TestHibernate { public static void main(String[] args) { Session sessionOne = HibernateUtil.getSessionFactory().openSession(); sessionOne.beginTransaction(); // Create new Employee object EmployeeEntity emp = new EmployeeEntity(); emp.setFirstName("Lokesh"); emp.setLastName("Gupta"); // Create new Employee object AccountEntity acc = new AccountEntity(); acc.setAccountNumber("DUMMY_ACCOUNT"); emp.setAccount(acc); //acc.setEmployee(emp); sessionOne.save(acc); sessionOne.save(emp); sessionOne.getTransaction().commit(); Integer genEmpId = emp.getEmployeeId(); Integer genAccId = acc.getAccountId(); Session sessionTwo = HibernateUtil.getSessionFactory().openSession(); sessionTwo.beginTransaction(); EmployeeEntity employee = (EmployeeEntity) sessionTwo.get(EmployeeEntity.class, genEmpId); AccountEntity account = (AccountEntity) sessionTwo.get(AccountEntity.class, genAccId); System.out.println(employee.getEmployeeId()); System.out.println(employee.getAccount().getAccountNumber()); System.out.println(account.getAccountId()); System.out.println(account.getEmployee().getEmployeeId()); HibernateUtil.shutdown(); } } Output: Hibernate: insert into Account (ACC_NO, employee_ID, ID) values (?, ?, ?) Hibernate: insert into Employee (account_ID, FIRST_NAME, LAST_NAME, ID) values (?, ?, ?, ?) Hibernate: select employeeen0_.ID as ID1_1_0_, employeeen0_.account_ID as account_4_1_0_, employeeen0_.FIRST_NAME as FIRST_NA2_1_0_, employeeen0_.LAST_NAME as LAST_NAM3_1_0_, accountent1_.ID as ID1_0_1_, accountent1_.ACC_NO as ACC_NO2_0_1_, accountent1_.employee_ID as employee3_0_1_, employeeen2_.ID as ID1_1_2_, employeeen2_.account_ID as account_4_1_2_, employeeen2_.FIRST_NAME as FIRST_NA2_1_2_, employeeen2_.LAST_NAME as LAST_NAM3_1_2_ from Employee employeeen0_ left outer join Account accountent1_ on employeeen0_.account_ID=accountent1_.ID left outer join Employee employeeen2_ on accountent1_.employee_ID=employeeen2_.ID where employeeen0_.ID=? 20 DUMMY_ACCOUNT 10 Exception in thread "main" java.lang.NullPointerException at com.howtodoinjava.test.TestHibernate.main(TestHibernate.java:43) ``` 您會看到我已經在客戶實體中設置了帳戶實體,所以我能夠得到它。 但是我注解了“`acc.setEmployee(emp);`”行,因此未在帳戶實體內部設置雇員實體,因此我無法獲取它。 還要注意上面的插入查詢。 這兩個表都具有與列名`employee_ID`和`account_ID`對應的外鍵關聯。 它是數據中**循環依賴項**的示例,可以隨時輕松關閉您的應用。 要正確存儲上述關系,必須取消注釋“`acc.setEmployee(emp);`”行。 取消注釋該行后,您將能夠根據需要存儲和檢索關聯,但是仍然存在循環依賴項。 取消注釋該行后,輸出將如下所示: ```java Hibernate: insert into Account (ACC_NO, employee_ID, ID) values (?, ?, ?) Hibernate: insert into Employee (account_ID, FIRST_NAME, LAST_NAME, ID) values (?, ?, ?, ?) Hibernate: update Account set ACC_NO=?, employee_ID=? where ID=? Hibernate: select employeeen0_.ID as ID1_1_0_, employeeen0_.account_ID as account_4_1_0_, employeeen0_.FIRST_NAME as FIRST_NA2_1_0_, employeeen0_.LAST_NAME as LAST_NAM3_1_0_, accountent1_.ID as ID1_0_1_, accountent1_.ACC_NO as ACC_NO2_0_1_, accountent1_.employee_ID as employee3_0_1_, employeeen2_.ID as ID1_1_2_, employeeen2_.account_ID as account_4_1_2_, employeeen2_.FIRST_NAME as FIRST_NA2_1_2_, employeeen2_.LAST_NAME as LAST_NAM3_1_2_ from Employee employeeen0_ left outer join Account accountent1_ on employeeen0_.account_ID=accountent1_.ID left outer join Employee employeeen2_ on accountent1_.employee_ID=employeeen2_.ID where employeeen0_.ID=? 20 DUMMY_ACCOUNT 10 20 ``` #### 方案 2)由單個實體管理的關聯 假設關聯是由`EmployeeEntity`管理的,那么兩個實體中的注解將如下所示。 ```java //Inside EmployeeEntity.java @OneToOne AccountEntity account; //Inside AccountEntity.java @OneToOne (mappedBy = "account") EmployeeEntity employee; ``` 現在告訴 Hiberate ,該關聯是由`EmployeeEntity`管理的,我們將在`AccountEntity`中添加`mappingBy`屬性以使其易于管理。 現在,要測試上述代碼,我們將只需要使用“`emp.setAccount(acc);`”設置一次關聯,并且由員工實體來管理該關系。 `AccountEntity`不需要明確地知道任何事情。 讓我們看看下面的測試運行。 ```java Session sessionOne = HibernateUtil.getSessionFactory().openSession(); sessionOne.beginTransaction(); // Create new Employee object EmployeeEntity emp = new EmployeeEntity(); emp.setFirstName("Lokesh"); emp.setLastName("Gupta"); // Create new Employee object AccountEntity acc = new AccountEntity(); acc.setAccountNumber("DUMMY_ACCOUNT"); emp.setAccount(acc); //acc.setEmployee(emp); sessionOne.save(acc); sessionOne.save(emp); sessionOne.getTransaction().commit(); Integer genEmpId = emp.getEmployeeId(); Integer genAccId = acc.getAccountId(); Session sessionTwo = HibernateUtil.getSessionFactory().openSession(); sessionTwo.beginTransaction(); EmployeeEntity employee = (EmployeeEntity) sessionTwo.get(EmployeeEntity.class, genEmpId); AccountEntity account = (AccountEntity) sessionTwo.get(AccountEntity.class, genAccId); System.out.println(employee.getEmployeeId()); System.out.println(employee.getAccount().getAccountNumber()); System.out.println(account.getAccountId()); System.out.println(account.getEmployee().getEmployeeId()); HibernateUtil.shutdown(); Output: Hibernate: insert into Account (ACC_NO, ID) values (?, ?) Hibernate: insert into Employee (account_ID, FIRST_NAME, LAST_NAME, ID) values (?, ?, ?, ?) Hibernate: select employeeen0_.ID as ID1_1_0_, employeeen0_.account_ID as account_4_1_0_, employeeen0_.FIRST_NAME as FIRST_NA2_1_0_, employeeen0_.LAST_NAME as LAST_NAM3_1_0_, accountent1_.ID as ID1_0_1_, accountent1_.ACC_NO as ACC_NO2_0_1_ from Employee employeeen0_ left outer join Account accountent1_ on employeeen0_.account_ID=accountent1_.ID where employeeen0_.ID=? Hibernate: select employeeen0_.ID as ID1_1_1_, employeeen0_.account_ID as account_4_1_1_, employeeen0_.FIRST_NAME as FIRST_NA2_1_1_, employeeen0_.LAST_NAME as LAST_NAM3_1_1_, accountent1_.ID as ID1_0_0_, accountent1_.ACC_NO as ACC_NO2_0_0_ from Employee employeeen0_ left outer join Account accountent1_ on employeeen0_.account_ID=accountent1_.ID where employeeen0_.account_ID=? 20 DUMMY_ACCOUNT 10 20 ``` 您會看到您不需要告訴帳戶實體任何內容(“`acc.setEmployee(emp)`”已注解)。 員工實體通過兩種方式管理關聯。 另一個觀察結果是關于外鍵列,我們現在只有一個外鍵列,即`account_ID`是`Employee`表。 因此也沒有循環依賴。 都好。 ## 定義各種映射關聯的指南 上面的示例顯示了如何在一對一映射中管理實體之間的關聯。 在上面的示例中,我們也可以選擇由`AccountEntity`管理的關聯,并且只需進行較小的代碼更改即可完成所有工作。 但是,在其他映射的情況下(例如,一對多或多對一),您將無法隨意定義關聯。 您需要規則。 下表顯示了如何選擇關系的一方,該一方應成為雙向關聯的所有者。 **請記住,要使關聯成為所有者,您必須將另一端標記為被另一端映射**。 | **關聯類型** | **選項/用法** | | --- | --- | | 一對一 | 可以將任一端作為所有者,但應其中之一(只有一個); 如果您未指定此選項,則最終會產生循環依賴項。 | | 一對多 | 多的一端必須成為聯合的所有者。 | | 多對一 | 這與從相反的角度看的一對多關系相同,因此適用相同的規則:必須使多的一端成為關聯的所有者。 | | 多對多 | 關聯的任何一端都可以成為所有者。 | 如果這一切看起來都令人困惑,請記住**關聯所有權僅與數據庫**中外鍵的管理有關。 我建議您閱讀之前的教程,討論“[**一對一映射**](//howtodoinjava.com/hibernate/hibernate-one-to-one-mapping-using-annotations/ "Hibernate one-to-one mapping using annotations")”,“[**一對多映射**](//howtodoinjava.com/hibernate/hibernate-one-to-many-mapping-using-annotations/ "Hibernate one-to-many mapping using annotations")”和“[**多對多映射**](//howtodoinjava.com/hibernate/hibernate-many-to-many-mapping-using-annotations/ "Hibernate many-to-many mapping using annotations")”的詳細信息。 他們將幫助您建立更強大的概念。 如果您有任何問題,請在下面給我留言。 **祝您學習愉快!**
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看