2011-09-27 143 views
2

我有以下的现有DB模式,我想用Java和原生的JPA注解来重新创建(使用Hibernate作为供应商,所以冬眠具体说明会工作作为最后的手段),其中:JPA复合键@OneToMany

CREATE TABLE users (
    user_id NUMBER NOT NULL      -- pk 
); 

CREATE TABLE userdata_keys (
    userdata_key_id NUMBER NOT NULL,   -- pk 
    key VARCHAR2(128) NOT NULL     
); 

CREATE TABLE users_userdata (
    user_id NUMBER NOT NULL,     -- fk users.user_id 
    userdata_key_id NUMBER NOT NULL,   -- fk userdata_keys.userdata_key_id 
    value VARCHAR2(256)       
); 

我由此产生了以下类和注解:

class User { 
    @Id 
    Long id; 
    @OneToMany 
    Set<Userdata> userdata; 
} 

class UserdataKey { 
    @Id 
    Long id; 
    String key; 
} 

class Userdata { 
    String value; 
    @EmbeddedId 
    UserdataId userdataId; 
} 

@Embeddable 
class UserdataId { 
    User user; 
    UserdataKey userdataKey; 
} 

我离开了COLUMNNAME属性和这里的实体的其他属性。
然而,它并不像预期的那样工作。 如果我没有指定一个mappedBy属性为user.userdata,hibernate会自动创建一个表USERS_USERS_USERDATA,但据我所见不会使用它。但它确实使用我为用户数据类指定的表。

因为我对Java和hibernate还不太熟悉,所以我现在要做的测试是查看hibernate在持久化几个样本条目时创建的数据库模式。

因此,我完全不知道我是否正确地做到了这一点。我阅读了hibernate文档和相当多的Google结果,但他们都没有处理我想要做的事情(组合键与“子类”以及它们自己的主键)。

+0

有一个类似的问题:http://stackoverflow.com/questions/31600142/how-to-define-onetomany-in-parent-entity-when-child-has-composite-pk – amphibient

回答

3

mappedBy属性在每个双向关联的一侧是必需的。当关联是一对多时,mappedBy属性放置在单侧(即在您的案例的Useruserdata字段中)。

这是因为当一个关联是双向的时,关联的一边总是与另一边相反,因此不需要告诉Hibernate两次关联如何映射(即使用哪个连接列或连接表) 。

如果您准备重新创建架构,我会做对(并且更容易),并在users_userdata中使用代理自动生成的密钥,而不是复合型。在应用程序的所有层中,这将更容易处理。

+0

我想我会采取你的建议并添加一个代理主键。 我猜自动生成的表是由于协会的“另一面”?不应该冬眠至少警告这一点? 我会用什么'mappedBy'属性?使用'userdataId.user'似乎可行,但我期望'userdataId'是正确的(这会产生一个关于具有不同数量的列的主键的错误)。 – user967058

+0

是的,生成的表是由于关联的另一侧没有mappedBy属性。不,它不应该警告:你可能有两个不同的单向关联,一个在一个方向,另一个在另一个方向(例如:一个人有很多孩子,一个孩子有一个老师:两个不同的关系,所以两个不同的映射)。 –

+0

它现在似乎与代理主键一起工作。非常感谢! – user967058