не может удалить сущность, у которой есть коллекция как дочерняя с hibernate - PullRequest
0 голосов
/ 29 марта 2011

ПРИМЕЧАНИЕ:

Это сообщение о круасе по адресу: hibernate forum

Поскольку я не получил ответа, поэтому я прошу здесь посмотреть, могу ли я получить некоторую помощь,:)

Если это будет решено здесь, я выложу ответ в спящем форуме.:)


В моем приложении у меня есть несколько сущностей, которым принадлежат некоторые коллекции, когда я понятия не имею, как их удалить.

Это основные коды моей работы:

Код:

@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;
   }
}

В БД есть таблицы "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()

Я получил ошибку сейчас, нозадача фактически не удаляется.

Я установил каскад в отображении.например, для шагов задачи в объекте задачи я устанавливаю cascade.type = all, поэтому я думаю, что когда hibernate пытается удалить задачу, она должна также удалить свои реализованные шаги задачи, а когда она пытается удалить объект шага задачи, онаобнаружит, что таблица «t_step_t_operator» ссылается на идентификатор в «t_step», поэтому я также установил «cascade = all» для поля «step» в классе задач.Но похоже, что происходит не то, что я думал ....

В чем проблема?Я схожу с ума!

Кто-нибудь может сделать мне одолжение?

BWT, что означает каскад?

Например: в вызове TaskStep у меня естьСписок операторов;

   //Class:TaskStep.
   @ManyToMany(
         cascade = CascadeType.ALL)
   @LazyCollection(LazyCollectionOption.FALSE)
   public List<Operator> getOperator() {
      return operator;
   }

В приведенном выше примере я установил cascade = all, означает ли это, что независимо от того, какая операция (curd) для TaskStep, он будет выполнять ту же операцию с Opeartors?

Ответы [ 2 ]

2 голосов
/ 29 марта 2011

Если вы хотите (имитировать) двунаправленное отношение без таблицы соединения, вы должны сделать это, создав два однонаправленных отношения и проинформировать Hibernate об отношении между ними - используя mappedBy, как говорит JB Nizet, но также сохраняя другие (@ManyToOne) mapping

@ JoinColumn можно использовать, например, если вы хотите отобразить только сторону @OneToMay отношения, но при этом не хотите таблицы объединения - вы укажете столбец в другой таблице, которая должна использоваться, обычно это однонаправленные ссылки не влияет на ссылочную таблицу и вместо этого использует таблицы соединения. В этом случае вам, вероятно, не нужен @JoinColumn, поскольку по умолчанию PK (id) используется в ограничениях FK в двунаправленных отношениях (столбец t_taskstep.task_id будет иметь ограничение FK для t_task.id)

Каскадный атрибут приведет к тому, что действия Create / Delete (обновления неявно обрабатываются EntityManager / Session) над владельцами сущностей будут каскадно касаться (в вашем случае) всех сущностей в Коллекции. Таким образом, удаление задачи также приведет к удалению всех экземпляров TaskSteps в вашей коллекции шагов, а также к удалению оператора Operator в TaskStep. Храбрый, но, скорее всего, потерпит неудачу, поскольку у вас есть отношения @ManyToMany - другие экземпляры TaskStep могут ссылаться на того самого оператора, к которому относится ваше удаление. Обычно только каскадное сохранение-обновление (или сопоставление отношений в компоненте / встраивание) и ручное удаление вручную. Если вы уверены, что ваша коллекция является единственной ссылкой на другую сущность, вы можете использовать ALL, а также DELETE-ORPHAN и, таким образом, вызывать удаление ссылочных сущностей, просто удаляя их из Collection.

@ IndexColumn используется, если вы хотите, чтобы порядок объектов в Списке запоминался. Если вас это не волнует, пропустите это, и у вашего отношения будет семантика Bag (неупорядоченная, допускается дублирование). Часто вы не хотите видеть дубликаты в коллекции, поэтому следует использовать коллекцию наборов.

Отчасти длинный ответ, извините. Возможно, следовало просто предоставить код.

1 голос
/ 29 марта 2011

Ваше отношение между Task и TaskStep отображается дважды: один раз в Task и один раз в TaskStep. @JoinColumn in Task должен исчезнуть, а @OneToMany должен иметь атрибут "mappedBy":

@OneToMany(cascade = CascadeType.ALL, mappedBy = "task")
@LazyCollection(LazyCollectionOption.FALSE)
@IndexColumn(name = "position")
public List<TaskStep> getSteps() {
    return steps;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...