2012-06-15 58 views
3

我试图创建一个使用下表结构JPA一个@OneToMany关系。如何在没有JoinTables的情况下在JPA中创建一对多关系?

+----------------+ 
| CATALOG  | 
+----------------+ 
| catalogId : PK | 
| name   | 
+----------------+ 
     | 
+----------------+ 
| PRODUCT  | 
+----------------+ 
| productId : PK | 
| name   | 
| catalogId : FK | 
+----------------+ 

我已经定义的类为

@Entity 
public class Catalog { 
    @Id 
    @GeneratedValue 
    long catalogId; 

    @OneToMany(cascade = CascadeType.ALL, 
       orphanRemoval = true, fetch = FetchType.LAZY) 
    @JoinColumn(name = "catalogId", 
       nullable = false, insertable = true, updatable = true) 
    Set<Product> products = new HashSet<>(); 

    String name; 
} 

@Entity 
public class Product { 
    @Id 
    @GeneratedValue 
    long productId; 

    String name; 
} 

然而,当我尝试坚持的目录对象的EclipseLink不放在采用catalogId值如预期,我得到一个SQL违反约束,有是空的。

而且,我不需要也不想要在产品端的@ManyToOne。

持久性代码:

final Catalog catalog = new Catalog(); 
catalog.name = text; 
final Product p = new Product(); 
p.name = text; 
catalog.products.add(p); 
em.persist(catalog); 

堆栈跟踪:

javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: Column 'CATALOGID' cannot accept a NULL value. 
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1367) 
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1295) 
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1301) 
    at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:866) 
    at net.trajano.maven_jee6.ws_mdb_ejb_web.TextMessages.putText(TextMessages.java:61) 
+0

您正在使用什么数据库? id列自动增量还是您有一些序列发生器?尝试给id一个值,并保存,如果它的工作。 –

+0

我认为你的问题与关系无关,我认为它与主键声明有关。看到我的答案。 – artaxerxe

+0

我使用的是Hibernate的实体管理器(虽然的EclipseLink或OpenJPA将最终部署) –

回答

6

当你给一个列的所有权上一个表Product(产品)到另一个实体Catalog(目录),该列将作为持久性的一部分进行更新和维护目录,而不是持续产品的一部分。该框架将创建一个产品,但由于FK列由另一个实体“拥有”,它将使用持久化目录时生成的单独更新语句来填充它。您需要将列设为空或将列的所有权放置在映射表的同一个实体上。

+0

我知道它的工作原理,如果我让它可空=真,但是,这并不真正符合事实,即不能没有目录 –

+0

任何产品我没有写规范,只是解释了为什么可空=真需要为它工作:)给予这对不同的表定义的列的实体的所有权是在一般PITA – Affe

+0

苏茨基因为它的声音,这是正确的答案:/我想一个DBA会生气,如果他出手这个约束是因为它不是正确的数据建模。 –

0

使产品类这样的,然后再试一次 -

@Entity 
public class Product { 
    @Id 
    @GeneratedValue 
    long productId; 

    @ManyToOne(fetch=FetchType.LAZY) 
    @JoinColumn(name = "catalogId", updatable = false, insertable = false, nullable=false) 
    private Catalog catalog ; 

    String name; 
} 
+0

它不工作,在内存中的德比实例,并违反我把约束“还有,我不需要也不想要一个@ManyToOne在产品端“。 –

1

我认为这是由于缺乏@GeneratedValue注释(与Postgres)的。根据我的经验,与Postgres,您的注释不起作用。您需要指定@SequenceGenerator@GeneratedValue。这里有一个例子:



    @SequenceGenerator(name = "lan_generator", sequenceName = "lan_pkey_seq") 
    @Id 
    @GeneratedValue(generator = "lan_generator") 
    @Column(name="id", unique=true, nullable=false) 
    private Integer id; 

如果您正在使用其他数据库的工作,试图解决你的。无论如何,在giveb链接中,当你使用MySQL时,你有一个可能的解决方案。也许它也适用于你的“内存德比实例”。

How to annotate MYSQL autoincrement field with JPA annotations

相关问题