2010-12-15 34 views
0

我有簡單的3個表:爲什麼不能使用JPA TopLink註釋來加入第三個表?

Users 
-id 
-name 

Addresses 
-id 
-user_id //FK 
-location 

Phone 
-id 
-number 
-address_id //FK 
  • 用戶可以有多個地址
  • 地址可以有很多電話

因此,應用到每個實體類的註解會是什麼樣子:

用戶

@OneToMany(cascade = CascadeType.ALL, mappedBy = "user") 
    private List<Addresses> addresses; 

地址

@ManyToOne() 
    @JoinColumn(name = "user_id") 
    private Users user; 

    @OneToMany(mappedBy = "address") 
    private List<Phone> phone; 

電話

@ManyToOne() 
    @JoinColumn(name = "address_id") 
    private Addresses address; 

上面的標註應該建立關係:

users (1) ----- (n) addresses (1) ------ (n) phone 

然後,我創建了一些測試達ta在MySQL中,並試圖運行測試,以查看返回「用戶」的查詢結果是否包含對地址和電話的引用。

我試着用2張表只使用用戶和地址,並得到了結果ok。

現在,我添加了「電話」表,這是第三表,然後我得到如下所示的錯誤。 這真的是正確的方式來加入3個或更多的表?

測試代碼

 try { 
      //get entity manager 
      String WEB_PU = "NoJSFPU"; 
      EntityManagerFactory factory =     Persistence.createEntityManagerFactory(WEB_PU); 
      EntityManager em = factory.createEntityManager(); 

      //run query 
      List<Users> usersList = em.createQuery("SELECT u FROM Users u").getResultList(); 

      //loop to print out each result 
      for(Users item : usersList) { 
       //display user info 
       System.out.println(item.getId() + " " + item.getFirstname()); 

       List<Addresses> addrs = item.getAddresses(); 
       for(Addresses ad : addrs) { 
        //display address info 
        System.out.println("Address:::" + ad.getLocation()); 

        List<Phone> pho = ad.getPhone(); 
        for(Phone p : pho) { 
        //display phone info 
        System.out.println("phone#" + p.getNumber()); 
        } 

       }//end inner for 
      }//end outer for 
       System.out.println("=========================="); 

      } 
      catch(Exception e) { 
       System.out.println("seriously wtf: " + e.toString()); 
       System.exit(1); 
      } 

錯誤

Exception Description: predeploy for PersistenceUnit [NoJSFPU] failed. 
Internal Exception: Exception [TOPLINK-7250] (Oracle TopLink Essentials - 2.0.1 (Build b09d-fcs (12/06/2007))): oracle.toplink.essentials.exceptions.ValidationException 
Exception Description: [class local.test.session.Addresses] uses a non-entity [class local.test.session.Phone] as target entity in the relationship attribute [private java.util.List local.test.session.Addresses.phone]. 
+2

PSSH,我將用戶名和地址表重命名爲User和Address。不要在表名中使用複數形式(也不要在實體類的類名中使用複數形式)。 – BalusC 2010-12-15 12:06:59

+0

嗨BalusC,很長一段時間看!感謝您的建議,但使用單數表名的原因是什麼?它是標準化的約定嗎? – 2010-12-15 23:38:17

回答

1

我想通了。必須使用@JoinTable註解來指定。

現在如果我運行測試代碼,可以獲得來自所有3個表中的數據:d

地址

@ManyToOne 
@JoinTable(name = "Addresses", joinColumns = {@JoinColumn(name="user_id", 
referencedColumnName = "user_id") }) 
private Users user; 

電話

@ManyToOne 
@JoinTable(name = "Phone", joinColumns = {@JoinColumn(name="address_id", 
referencedColumnName = "address_id") }) 
private Addresses address;