аннотации JPA один ко многим не удаляют сирот - PullRequest
0 голосов
/ 15 ноября 2009

Я пытаюсь создать пользователя и проект управления контактами. У меня много классов, поэтому я ограничусь тем, что здесь касается. у меня есть userAccount, userProfile и группа вот отображение учетной записи пользователя

@Id @GeneratedValue
@Column(name="USER_ACCOUNT_ID")
private Long ID; 
 ......
 @Column(name="EMAIL", length=100, unique=true)
private String email;

@OneToOne(targetEntity=UserProfileImpl.class,cascade={CascadeType.ALL})
 @org.hibernate.annotations.Cascade(value=org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
@JoinColumn(name="USER_PROFILE_ID")
private UserProfile profile;

 @OneToMany(targetEntity=GroupImpl.class, cascade={CascadeType.ALL})
 //    @JoinColumn(name="USER_ACCOUNT_ID")
@JoinTable(name = "USER_ACCOUNT_CONTACT_GROUP", joinColumns = @JoinColumn(name = "USER_ACCOUNT_ID"), inverseJoinColumns = @JoinColumn(name = "GROUP_ID"))
@org.hibernate.annotations.Cascade(value=org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
private Set<Group> groups = new HashSet<Group>();
........

вот пользовательский профиль

@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="USER_PROFILE_ID")
private Long ID;
.....
 @OneToOne(mappedBy="profile", targetEntity=UserAccountImpl.class)
private UserAccount userAccount;
.....

вот группа

@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="GROUP_ID")
private Long ID;    
.......
@Column(name="NAME", length=100, unique=true)
private String Name;

@ManyToOne(targetEntity=UserAccountImpl.class)
@JoinColumn(name="USER_ACCOUNT_ID",nullable=false)
private UserAccount userAccount;

так что в основном это так. Все прошло нормально, прежде чем двунаправленная ассоциация добавила объект userAccount в group.so при тестировании. я создаю userProfile, userAccount и группу (используя spring @autowired).
В методе setUP (@Before) я установил несколько prop для userProfile и добавил его в useAccount вместе со своим prop и сохранил его, а затем установил useAccount для группы.
на tearDown (@After) я удаляю учетную запись пользователя.
на моем testSave (сохраняет группу) работает нормально (использует один и тот же сеанс для всех операций), но на консоли нет запроса sql delete для группы, но он удаляет userAccount Хотя.
Удаляя userAccount в методе teardown, я надеялся, что группа должна быть удалена. Но это не так.
хуже из-за уникального ограничения на имя группы, другие тесты не работают. Я ищу в сети, но все, что я пытаюсь, похоже, не работает. Кто может спасти меня :)? Я имею в виду, как я должен это сделать? спасибо за чтение

это обновление того, что я пробовал, основываясь на полученном ответе. я добавил это к group.setUserAccount(null) к своему removeGroup, которое теперь является

public void removeGroup(Group group) {
    try{
       if(this.groups.contains(group)){
        group.setUserAccount(null);
        this.groups.remove(group);
       }
    } catch(Exception ex){
        ex.printStackTrace();
    }
}

так что для теста, который я использовал, который имеет такое же поведение, т.е. удаляет учетную запись пользователя, но не группу

ua1.removeGroup(g1);
uaDao.delete(ua1);

Я думаю, он не входит в блок if, потому что у меня должно быть такое же поведение, как у этого:

 g1.setUserAccount(null);
 uaDao.delete(ua1);

этот другой выдает ошибку

PropertyValueException: свойство not-null ссылается на нулевое или временное значение

так что я думаю, что я удалю группу, используя:

gDao.delete(g1);
uaDao.delete(ua1);

в надежде, что я найду способ это сделать. Спасибо людям, которые помогли мне, особенно Паскалю, если у вас была другая идея или вы нашли что-то не так с моим кодом, я буду более чем рад исправить это. чтение

Ответы [ 2 ]

2 голосов
/ 15 ноября 2009

Прежде всего, если отношение UserAccount -> Group является двунаправленным, то вам необходимо сопоставить обратную сторону сбора как

@OneToMany(targetEntity=GroupImpl.class, cascade{CascadeType.ALL},mappedBy="userAccount")

Итак, теперь Hibernate знает, что UserAccount является владельцем коллекции. Теперь для удаления, поскольку @Pascal говорит, что вам нужно отсоединить обе стороны. Поскольку Hibernate игнорирует коллекцию, владелец отвечает за связывание отношений, поэтому в основном вспомогательный метод, подобный этому, создает ассоциацию в UserAccount

public void addGroup(Group group){
     group.setUserAccount(this);
     groups.add(group);
}

теперь для удаления другого вспомогательного метода

public void removeGroup(Group group){
    group.setUserAccount(null);
    groups.remove(group);
}

теперь для удаления

UserAccount ua = //load user account object
for(Group g : ua.getGroups())
      ua.removeGroup(g);

session.delete(ua);

Ваш код должен работать сейчас. Вы не должны делать это по-моему, но я надеюсь, что вы получите дрейф. DELETE_ORPHAN должен позаботиться о вашем каскадном удалении groups

1 голос
/ 15 ноября 2009

Использование @Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN) нормально, но ...

Вы также устанавливаете ссылку userAccount в Group на null?

Вы по-прежнему должны управлять отношениями Java вручную, т. Е. Вы должны установить родительский элемент на null в дочернем, если отношение двунаправленное.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...