arquillianテストクラスから新しいOrderオブジェクトを永続化しようとしています。 注文エンティティには、主フィールドが4つの構成された主キーを持つOrderDetailエンティティのリストが含まれています。 @IdClassをHibernateとArquillianの組み合わせで使用するCascadeType.Insertは、複合主キーの一部であるManyToOne外部キーオブジェクトに挿入します。
しかし、Hibernateは新しいOrderDetailオブジェクトを挿入しようとしている一方で、それはまた、 ていない新たな Itemオブジェクト(項目がOrderDetailエンティティの主PK分野の一つと@IDで注釈を付けている)を挿入し、これは、その結果DB内のItemテーブルから一意の制約例外。Item @ OneToManyアノテーション からCascadeTypeを削除し、CascadeType.Refreshも試しましたが、同じ結果が得られましたが、何も変更されませんでした。これは、すべてのケースでCascadeType.Insertを強制的に使用するように機能します。予想通り、私はを使用するときには、がを働いた
ではなく@IdClass の注釈を@EmbeddedIdしかし、私はそれが@IdClassでは動作しなかった理由を知りたいですか? Hibernateのバグですか?それはJPA 2.1 specificationごとに完全に動作するはずです。
注文エンティティ
@Entity
@Table(name = "ORDERS")
public class Orders extends BaseEntity {
private static final long serialVersionUID = 1L;
@Id
@Column(name = "ORDERNO")
@GeneratedValue(strategy = GenerationType.AUTO)
private Long orderNo ;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "order", fetch = FetchType.LAZY)
private List<OrderDetail> orderDetailsList ;
// setters and getters
}
OrderDetailエンティティ
@Entity
@Table(name = "ORDERDETAILS")
@IdClass(OrderDetailsPK.class)
public class OrderDetail extends BaseEntity {
private static final long serialVersionUID = 1L;
@Id
@JoinColumn(name = "ORDERNO", referencedColumnName = "ORDERNO")
@ManyToOne(optional = false, fetch = FetchType.LAZY)
private Orders order;
@Id
@JoinColumn(name = "ITEMNO", referencedColumnName = "ITEMNO", insertable = false, updatable = false)
@ManyToOne(cascade = CascadeType.REFRESH,optional = false, fetch = FetchType.LAZY)
//@Cascade({CascadeType.DETACH}) // I tried this but did not work, it keep try to insert the item.
private Item item;
@Id
@Column(name = "LINETYPE")
private String lineType;
@Id
@Column(name = "PROMITEMNO")
private String promItemNo;
Itemエンティティの
@Entity
@Table(name = "ITEM")
public class Item extends BaseEntity {
private static final long serialVersionUID = 1L;
@Id
@Column(name = "ITEMNO")
private String itemno;
// setters and getters
@Override
public int hashCode() {
int hash = 0;
hash += (itemno != null ? itemno.hashCode() : 0);
return hash;
}
@Override
public boolean equals(Object object) {
if (!(object instanceof Item)) {
return false;
}
Item other = (Item) object;
System.out.println("Item Equal Method = " + !((this.itemno == null && other.itemno != null) || (this.itemno != null && !this.itemno.equals(other.itemno))));
return !((this.itemno == null && other.itemno != null) || (this.itemno != null && !this.itemno.equals(other.itemno)));
}
@Override
public String toString() {
return "com.unilever.sas.model.entities.masterdata.Item[ itemno=" + itemno + " ]";
}
}
OrderDetailsPK
public class OrderDetailsPK implements Serializable
{
private static final long serialVersionUID = 1L;
private Long order;
private String item;
private String lineType;
private String promItemNo;
public OrderDetailsPK() {
}
public OrderDetailsPK(Long order, String item, String lineType, String promItemNo) {
this.order = order;
this.item = item;
this.lineType = lineType;
this.promItemNo = promItemNo;
}
public Long getOrder() {
return order;
}
public String getItem() {
return item;
}
public String getLineType() {
return lineType;
}
public String getPromItemNo() {
return promItemNo;
}
@Override
public int hashCode() {
int hash = 5;
hash = 73 * hash + Objects.hashCode(this.order);
hash = 73 * hash + Objects.hashCode(this.item);
hash = 73 * hash + Objects.hashCode(this.lineType);
hash = 73 * hash + Objects.hashCode(this.promItemNo);
return hash;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final OrderDetailsPK other = (OrderDetailsPK) obj;
if (!Objects.equals(this.item, other.item)) {
return false;
}
if (!Objects.equals(this.lineType, other.lineType)) {
return false;
}
if (!Objects.equals(this.promItemNo, other.promItemNo)) {
return false;
}
if (!Objects.equals(this.order, other.order)) {
return false;
}
return true;
}
@Override
public String toString() {
return "OrderDetailsPK{" + "order=" + order + ", item=" + item + ", lineType=" + lineType + ", promItemNo=" + promItemNo + '}';
}
Arquillianテスト
@RunWith(Arquillian.class)
public class OrdersFacadeTest
{
@Inject
OrdersFacadeLocal ordersFacade ;
@Inject
ItemFacadeLocal itemFacade ;
@Test
public void testCreateOrder() throws Exception
{
Item item = itemFacade.find("20247912");
Orders order = new Orders();
OrderDetail orderDetail = new OrderDetail();
orderDetail.setOrder(order);
orderDetail.setItem(item);
orderDetail.setLineType("NLI");
orderDetail.setPromItemNo("99999");
List<OrderDetail> orderDeialsList = new ArrayList<>();
orderDeialsList.add(orderDetail);
order.setOrderDetailsList(orderDeialsList);
ordersFacade.create(order);
Orders createdOrder = ordersFacade.find(order.getOrderNo());
assertEquals(order, createdOrder);
}
この[投稿](https://stackoverflow.com/questions/3585034/how-to-map-a-composite-key-with-hibernate/)は、どのように動作するかを理解するのに役立ちます。 –
[テストケース](http://in.relation.to/2016/01/14/hibernate-jpa-test-case-template/)でレプリケートできれば、Jiraの問題を開く必要があります。 –