2010-12-15 32 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;