我正在学习Hibernate,刚刚阅读了《Java Persistance with Hibernate》一书的“7.2.3 添加列来连接表”一章。我的目标是在一次事务中保存 Item、Category 和 CategorizedItem。
那里有一个构造函数(第305页):
public CategorizedItem(String username, Category category, Item item) {
// Set fields
this.username = username;
this.category = category;
this.item = item;
// Set identifier values
this.id.categoryId = category.getId();
this.id.itemId = item.getId();
// Guarantee referential integrity
category.getCategorizedItems().add(this);
item.getCategorizedItems().add(this);
}
它接受类别和项目对象。如果我创建一个类别和一个项目并希望使用此技术将它们连接起来,那么显然必须在之前保留它们,因为category.getId() 和 item.getId() 返回 null。
是否有“Hibernate包中的技巧”可以级联保存连接表?连接表有附加列。我想将所有三个对象保存在网页 Controller 的 onSuccess 处理程序中。必须插入所有三个实体或都不插入任何实体。
最佳答案
你说
My goal is to save Item, Category and CategorizedItem in one transaction
Hibernate包里有没有一个技巧可以级联保存连接表?
是的,使用 MutableInt
@Entity
public class CategorizedItem implements Serializable {
private CategorizedItemId categorizedItemId;
private String userName;
private Category category;
private Item item;
/**
* required no-arg constructor
*/
public CategorizedItem() {}
public CategorizedItem(CategorizedItemId categorizedItemId) {
this.categorizedItemId = categorizedItemId;
}
public CategorizedItem(String userName, Category category, Item item) {
this.userName = userName;
this.categorizedItemId = new CategorizedItemId(category.getIdAsMutableInt(), item.getIdAsMutableInt());
}
@EmbeddedId
public CategorizedItemId getCategorizedItemId() {
return this.categorizedItemId;
}
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="CATEGORY_ID", insertable=false, updateable=false)
public Category getCategory() {
return this.category;
}
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="ITEM_ID", insertable=false, updateable=false)
public Item getItem() {
return this.item;
}
// setter's goes here
/**
* It MUST implements Serializable
* It MUST overrides equals and hashCode method
* It MUST has a no-arg constructor
*
* Hibernate/JPA 1.0 does not support automatic generation of compound primary key
* You SHOULD set up manually
*/
@Embeddable
public static class CategorizedItemId implements Serializable {
private MutableInt categoryId = new MutableInt(-1);
private MutableInt itemId = new MutableInt(-1);
/**
* required no-arg constructor
*/
public CategorizedItemId() {}
public CategorizedItemId(MutableInt categoryId, MutableInt itemId) {
this.categoryId = categoryId;
this.itemId = itemId;
}
@Column(name="CATEGORY_ID", updateable=false, nullable=false)
public Integer getCategoryId() {
return this.categoryId.intValue();
}
public void setCategoryId(Integer categoryId) {
return this.categoryId.setValue(categoryId);
}
@Column(name="ITEM_ID", updateable=false, nullable=false)
public Integer getItemId() {
return this.itemId.intValue();
}
public void setItemId(Integer itemId) {
return this.itemId.setValue(itemId);
}
// getter's and setter's
@Override
public boolean equals(Object o) {
if(!(o instanceof CategorizedItemId))
return null;
finalCategorizedItemId other = (CategorizedItemId) o;
return new EqualsBuilder().append(getCategoryId(), other.getCategoryId())
.append(getItemId(), other.getItemId())
.isEquals();
}
@Override
public int hashCode() {
return new HashCodeBuilder().append(getCategoryId())
.append(getItemId())
.toHashCode();
}
}
}
这里是类别
@Entity
public class Category implements Serializable {
public MutableInt id = new MutableInt(-1);
private List<CategorizedItem> categorizedItemList = new ArrayList<CategorizedItem>();
@Transient
public MutableInt getIdAsMutableInt() {
return this.id;
}
@Id
@GeneratedValue
public Integer getId() {
return this.id.intValue();
}
public void setId(Integer id) {
return this.id.setValue(id);
}
@OneToMany(mappedBy="category")
@JoinColumn(name="CATEGORY_ID", insertable=false, updateable=false)
@Cascade(CascadeType.SAVE_UPDATE)
public List<CategorizedItem> getCategorizedItemList() {
return categorizedItemList;
}
// setter's
/**
* Use this method when you have a saved Item
*/
public void addCategorizedItem(CategorizedItem categorizedItem) {
categorizedItem.setCategorizedItemId(new CategorizedItemId(getIdAsMutableInt(), categorizedItem.getItem().getIdAsMutableInt()));
categorizedItem.setCategory(this);
getCategorizedItemList().add(categorizedItem);
}
}
和项目
@Entity
public class Item implements Serializable {
public MutableInt id = new MutableInt(-1);
private List<CategorizedItem> categorizedItemList = new ArrayList<CategorizedItem>();
@Transient
public MutableInt getIdAsMutableInt() {
return this.id;
}
@Id
@GeneratedValue
public Integer getId() {
return this.id.intValue();
}
public void setId(Integer id) {
return this.id.setValue(id);
}
@OneToMany(mappedBy="item")
@JoinColumn(name="ITEM_ID", insertable=false, updateable=false)
@Cascade(CascadeType.SAVE_UPDATE)
public List<CategorizedItem> getCategorizedItemList() {
return this.categorizedItemList;
}
// setter's
/**
* Use this method when you have a saved Category
*/
public void addCategorizedItem(CategorizedItem categorizedItem) {
categorizedItem.setCategorizedItemId(new CategorizedItemId(getIdAsMutableInt(), categorizedItem.getCategory().getIdAsMutableInt()));
categorizedItem.setItem(this);
getCategorizedItemList().add(categorizedItem);
}
}
现在,因为在保存 CategorizedItem 之前您需要categoryId 和 itemId,请执行以下操作
Category category = new new Category();
Item item = new Item();
session.save(new Category());
session.save(new Item());
session.save(new CategorizedItem(userName, category, item));
请注意,只有当您有已保存的类别或已保存的项目时,级联才起作用。否则,您需要按照上面所示的方法进行操作
关于java - Hibernate - 具有附加列的链接表 - 保存在一个事务中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3528595/