注:
这是一个发帖:hibernate forum
由于我没有回答,所以我在这里问我是否可以得到一些帮助。 :)
如果在这里解决了这个问题,我将在hibernate论坛中发布答案。 :)
在我的应用程序中,当我不知道要删除它们时,我有一些拥有某些集合的实体。
这是我的核心代码:
代码:
@Entity
@Table(
name = "t_task")
public class Task {
private int id;
private List<TaskStep> steps = new ArrayList<TaskStep>();
public Task() {
this.createTime = new Date();
}
public Task(String name) {
this();
this.name = name;
}
@Id
@GeneratedValue
public int getId() {
return id;
}
@OneToMany(
cascade = CascadeType.ALL)
@JoinColumn(
name = "task_id",
nullable = false)
@LazyCollection(LazyCollectionOption.FALSE)
@IndexColumn(
name = "position")
public List<TaskStep> getSteps() {
return steps;
}
// domain method
public void addSteps(TaskStep ts) {
steps.add(ts);
ts.setTask(this);
}
public void removeStep(TaskStep ts) {
steps.remove(ts);
}
// setter
public void setId(int id) {
this.id = id;
}
public void setSteps(List<TaskStep> steps) {
this.steps = steps;
for (TaskStep st : steps) {
st.setTask(this);
}
}
}
//TaskStep:
@Entity
@Table(
name = "t_taskstep")
public class TaskStep {
private int id;
private List<Operator> operator = new ArrayList<Operator>();
private Task task;
public TaskStep() {}
@Id
@GeneratedValue
public int getId() {
return id;
}
@ManyToMany(
cascade = CascadeType.ALL)
@LazyCollection(LazyCollectionOption.FALSE)
public List<Operator> getOperator() {
return operator;
}
@ManyToOne
@JoinColumn(
name = "task_id",
nullable = false,
updatable = false,
insertable = false)
public Task getTask() {
return task;
}
// domain method start
public void addOperator(Operator op) {
operator.add(op);
}
// setter
public void setId(int id) {
this.id = id;
}
public void setOperator(List<Operator> operator) {
this.operator = operator;
}
public void setTask(Task task) {
this.task = task;
}
}
//Operator:
@Entity
@Table(
name = "t_operator")
public class Operator {
private int id;
private List<TaskStep> steps = new ArrayList<TaskStep>();
public Operator() {}
@Id
@GeneratedValue
public int getId() {
return id;
}
// //setter
public void setId(int id) {
this.id = id;
}
public void setSteps(List<TaskStep> steps) {
this.steps = steps;
}
@ManyToMany(
mappedBy = "operator")
public List<TaskStep> getSteps() {
return steps;
}
}
在db中,有“t_task”,“t_operator”,“t_step”,“t_step_operator”等表。
我用这种方式删除任务: 码: taskDao.delTaskById(5);
这是道:
代码:
public void delTaskById(int id) {
Task t = queryTaskById(id);
Session sess = factory.getCurrentSession();
try {
sess.beginTransaction();
sess.delete(t); // 1)
sess.flush();
sess.getTransaction().commit();
} catch (HibernateException e) {
sess.getTransaction().rollback();
}
}
我收到一条错误,上面写着“无法删除或更新父排......”。
然后我尝试使用repalce
sess.delete(t)
到
sess.createQuery("delete from Task t where t.id="+id).executeUpdate()
我现在收到错误,但实际上并没有删除任务。
我在映射中设置了级联。例如,对于任务对象中的taskstesps,我设置了cascade.type = all,所以我认为当hibernate尝试删除任务时,它也应该删除它的自己的任务步骤,并且当它尝试删除taskstep对象时,它会发现“t_step_t_operator”表引用了“t_step”中的id,所以我还为任务类中的“step”字段设置了“cascade = all”。 但似乎发生的事情并不是我想的......
有什么问题?我要疯了!
任何人都可以帮我一个忙吗?
BWT,级联是什么意思?
例如: 在TaskStep calss中,我有一个操作符列表;
//Class:TaskStep.
@ManyToMany(
cascade = CascadeType.ALL)
@LazyCollection(LazyCollectionOption.FALSE)
public List<Operator> getOperator() {
return operator;
}
在上面的例子中,我设置了cascade = all,这是否意味着无论对TaskStep进行什么操作(curd),它都会对Opeartors做同样的操作?
答案 0 :(得分:2)
如果你想要(模拟)没有连接表的双向关系,你必须通过创建两个单向关系并通知Hibernate关于它们之间的关系 - 通过使用mappedBy,如JB Nizet所说,但也保留另一个(@ManyToOne)映射
可以使用@JoinColumn,例如,如果您只想映射关系的@OneToMay端但仍然不想要连接表 - 您将指出应该使用的其他表中的列,通常是单向引用不影响引用的表,而是使用连接表。在这种情况下,你不需要@JoinColumn,因为默认情况下PK(id)用于双向关系中的FK约束(t_taskstep.task_id列将对t_task.id赋予FK约束)
Cascade属性将导致拥有实体的创建/删除操作(更新由EntityManager / Session隐式处理)以级联到(在您的情况下)Collection中的所有实体。因此,对任务执行删除操作也会导致删除步骤Collection中的所有TaskSteps实例,并删除TaskStep中的Operator运算符。勇敢,但由于涉及@ManyToMany关系可能会失败 - 其他TaskStep实例可能会引用您的删除级联的运算符。通常只有级联保存更新(或组件/嵌入式的映射关系)并手动处理删除。如果您确定您的集合是唯一一个引用另一个实体的集合,那么您可以使用ALL和DELETE-ORPHAN,从而只需将其从集合中删除即可删除引用的实体。
如果要记住列表中对象的顺序,则使用@IndexColumn。如果您不在乎,请跳过它,您的关系将具有Bag语义(无序,允许重复)。通常,您不希望在Collection中看到重复项,因此应该使用Set Collection。
有点长的答案,对不起。应该只是提供代码。
答案 1 :(得分:1)
您在Task和TaskStep之间的关系被映射两次:一次在Task中,一次在TaskStep中。任务中的@JoinColumn应该消失,而@OneToMany应该有一个“mappedBy”属性:
@OneToMany(cascade = CascadeType.ALL, mappedBy = "task")
@LazyCollection(LazyCollectionOption.FALSE)
@IndexColumn(name = "position")
public List<TaskStep> getSteps() {
return steps;
}