我有以下实体类的双向一个一对多的关系:
0或1的客户端< - > 0或多个产品订单
当坚持我想要的相关产品订单的实体被持久化,太客户端实体(如自己的外键“父”的客户可能已经更新)。
当然,所有需要CASCADE选项都在客户端设置。 但是,如果一个新创建的客户端持续了第一次这是行不通的,同时参照现有的产品订单在这种情况下:
- 产品订单“1”被创建和保持。 工作良好。
- 客户端“2”被创建和产品顺序“1”被添加到它的产品订单列表。 然后,它仍然存在。 不工作。
我试了apporaches,但它们都没有表现出预期的结果。 请参阅下面的结果。 我在这里阅读所有相关的问题,但他们并没有帮助我。 我将EclipseLink 2.3.0,纯JPA 2.0注释和JTA作为一个Apache德比(JavaDB之外)与内部存储器DB在GlassFish 3.1.2事务类型。 实体关系由JSF GUI管理。 对象级关系管理工作(除了持续存在的),我用JUnit测试进行了测试。
方法1)“默认”(基于NetBeans的类模板)
客户:
@Entity
public class Client implements Serializable, ParentEntity {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@OneToMany(mappedBy = "client", cascade={CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH},
fetch= FetchType.LAZY)
private List<ProductOrder> orders = new ArrayList<>();
// other fields, getters and setters
}
ProductOrder:
@Entity
public class ProductOrder implements Serializable, ChildEntity {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@ManyToOne // owning side
private Client client;
// other fields, getters and setters
}
通用持久门面:
// Called when pressing "save" on the "create new..." JSF page
public void create(T entity) {
getEntityManager().persist(entity);
}
// Called when pressing "save" on the "edit..." JSF page
public void edit(T entity) {
getEntityManager().merge(entity);
}
结果:
创建()立刻引发此异常:
警告:EJB ClientFacade方法public void javaee6test.beans.AbstractFacade.create(java.lang.Object中)javax.ejb.EJBException异常调用期间发生系统异常:事务终止...
javax.transaction.RollbackException:由交易造成的标记为回滚。 ...
产生的原因:异常[的EclipseLink-4002](Eclipse持久服务 - 2.3.0.v20110604-r9504):org.eclipse.persistence.exceptions.DatabaseException内部异常:java.sql.SQLIntegrityConstraintViolationException:国有包换被放弃,因为它会造成在一个独特的或主键约束或通过在“PRODUCTORDER”定义的“SQL120513133540930”识别的唯一索引重复键值。 错误代码:-1调用:(?,?)INSERT INTO PRODUCTORDER(ID,CLIENT_ID)值绑定=> [2个参数绑定]查询:InsertObjectQuery(javaee6test.model.ProductOrder [ID = 1])...
java.sql.SQLIntegrityConstraintViolationException:由此造成的语句已放弃,因为它会造成对“PRO-DUCTORDER”定义的唯一或主键约束或“SQL120513133540930”标识的唯一索引中的重复的键值。 ...
org.apache.derby.client.am.SqlException:由此造成的语句已放弃BE-因为它会在唯一或主键CON-straint或定义“SQL120513133540930”标识的唯一索引中导致重复键值“生产方-DER”。
我不明白这一点例外。 编辑()工作正常。 但我想,产品订单,在其创建时间添加到客户端,所以这是不够的。
方法2)合并()只
更改通用持久门面:
// Called when pressing "save" on the "create new..." JSF page
public void create(T entity) {
getEntityManager().merge(entity);
}
// Called when pressing "save" on the "edit..." JSF page
public void edit(T entity) {
getEntityManager().merge(entity);
}
结果:
在创建()时,的EclipseLink记录输出说道:
细:INSERT INTO CLIENT(ID,NAME,ADDRESS_ID)值绑定=> [3个参数结合](,?,??)
但对产品订单表号“UPDATE”。 因此,这种关系是不成立的。 再次,编辑(),而另一方面,做工精细。
Apporach 3)身份证GenerationType.IDENTITY两个实体类型
更改客户端和品阶等级:
...
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
...
结果:
在创建()时,的EclipseLink记录输出说道:
细:(?,?)INSERT INTO CLIENT(NAME,ADDRESS_ID)值绑定=> [2个参数绑定]
精细:值IDENTITY_VAL_LOCAL()
细:(?,?)INSERT INTO PRODUCTORDER(ORDERDATE,CLIENT_ID)值绑定=> [2个参数绑定]
精细:值IDENTITY_VAL_LOCAL()
因此,不是estabilshing以添加到客户端的列表中的产品订单有关系,创建一个新的prodcut秩序的实体和持久化(!),并以该实体的关系estabilshed。 同样在这里,编辑()工作正常。
Apporach 4)方法(2)和(3)组合的
结果:同方法(2)。
我的问题是: 有没有办法实现上述场景? 怎样才可以archieved? 我想留在JPA(无特定供应商的解决方案)。