坚持一对多的关系

时间:2010-06-24 17:51:00

标签: jpa java-ee persistence entity-relationship object-relational-model

我正在使用Java EE 6.只是想先把它扔出去 这是关系。 customer可以有多个facility 这是客户类

@Entity
public class Customer {
     @Id
     @GeneratedValue(strategy = GenerationType.AUTO)
     private Long id;
     private String name;
     @OneToMany(cascade=CascadeType.ALL)
     @JoinColumn(name="CUSTOMER_FK", nullable=false)
     private List<Facility> facilities;

     public Customer(){
          facilities = new ArrayList<Facility>();
     }

     public Customer(Long id, String name, List<Facility> facilities) {
          this.id = id;
          this.name = name;
          this.facilities = facilities;
     }
     //set and get method
     ...

     public void addFacility(Facility facility){
          this.facilities.add(facility);
     }
}

这是设施类

@Entity
public class Facility {
     @Id
     @GeneratedValue(strategy = GenerationType.AUTO)
     private Long id;
     private String name;

     public Facility(){}

     public Facility(Long id, String name, Address address, List<Project> project) {
          this.id = id;
          this.name = name;
     }

     //Set and get method
     ...
}

现在主要是如果我有这个,那么它工作正常。我可以看到这个插入我的数据库

Customer customer = new Customer();
customer.setName("Wake Forest University");
EntityManagerFactory emf = Persistence.createEntityManagerFactory("EntityLibraryPU");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
em.persist(customer);
tx.commit();

然而,只要我尝试添加设施并强制FK约束。事情开始破裂。

Customer customer = new Customer();
customer.setName("Wake Forest University");
Facility facility = new Facility();
facility.setName("Xia");
customer.addFacility(facility);
EntityManagerFactory emf = Persistence.createEntityManagerFactory("EntityLibraryPU");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
em.persist(customer);
tx.commit();

这是错误。首先,我得到同一个“Wake Forest University”客户插入CUSTOMER表的两倍(不name属性未设置为唯一,它是一次将两个条目插入数据库)。但是,没有任何内容可以插入到我的FACILITY表中。知道为什么吗?其中一个错误代码是Field 'customer_fk' doesn't have a default value。也许这可以暗示你们一点点。我不知道。当我查看错误日志:Call: INSERT INTO FACILITY (ID, NAME, STREET2, STREET1, ZIPCODE, STATE, CITY, COUNTRY) VALUES (?, ?, ?, ?, ?, ?, ?, ?)bind => [2, Xia, null, null, null, null, null, null]时,我的FACILITY表中有一个字段CUSTOMER_FK,当我尝试强制{{1}之间的一对多关系时创建该字段CUSTOMER }和FACILITY,但查询永远不会在该字段中插入任​​何内容

2 个答案:

答案 0 :(得分:2)

  

首先,我将同一个“Wake Forest University”客户插入CUSTOMER表中的两倍

好吧,你没有在name实体的Customer上定义任何唯一性约束,所以没有什么能阻止这种情况(两个记录都有不同的PK)。如果要强制name的唯一性,请设置唯一约束:

@Column(unique=true)
String name;
  

其中一个错误代码是字段'customer_fk'没有默认值。

我认为评论的行是“有罪”:

tx.begin();
em.persist(customer);
//em.persist(facility); //DON'T DO THIS
tx.commit();

首先,该设施对其客户一无所知(这是一个单向关联,从CustomerFacitlity),因此JPA无法设置FK,因此错误消息。

其次,因为您正在将{strong>所有操作从Customer级联到Facilitycascade=CascadeType.ALL注释中的@OneToMany,您不需要persist facility实例。

所以,只是不要在facility实例上调用persist,让JPA从customer级联内容。

答案 1 :(得分:1)

您获得了重复命名的客户,因为name列上没有唯一约束,因此运行第二个测试会再次添加相同的命名客户。将unique=true添加到客户名称,该列将被强制为唯一。然后,您将遇到无法创建具有相同名称的第二个客户的问题。

不需要明确保存工具,因为在您保存客户时也会以级联方式保存工厂。

事实上,你也不能直接坚持设施,因为它没有自己的桌子。通过使用@JoinColumn,您可以删除Customer和Facility之间的连接表的使用,并将客户外键放在Facuility表中。如果删除@JoinColumn,那么您将看到一个像CUSTOMER_FACILITY这样的附加连接表,它存储客户到设施的映射。然后,您可以独立持有设施。