ManyToMany предлагает удалить запись в таблице присоединений - PullRequest
4 голосов
/ 17 января 2010

Я использую эти две сущности для создания нового пользователя и связанных с ним групп:

@Entity  
@Table(name="usertable")  
@SuppressWarnings("serial")  
@Searchable  
public class User implements Serializable {  

    @GeneratedValue(generator="userIdSeq")  
    @SequenceGenerator(name="userIdSeq", sequenceName="usertable_id_seq")      
    @SearchableId  
    @Id  
    int id;  

    @SearchableProperty  
    String userId;                      // 'Unique identifier. It is formed using this fashion: ''prefix:identifier''  
    String userName;                    // Name used to log in the application.  
    String email;                       // User's email  

    @ManyToMany  
    @JoinTable( name="usergroup",  
                joinColumns=@JoinColumn(name = "userid", referencedColumnName="userId"),  
                inverseJoinColumns=@JoinColumn(name = "groupid")  
    )  
    List<Group> groups;  

    ...  
}  

// Group  
@Entity  
@Table(name="grouptable")  
public class Group implements Serializable {  
    @Id  
    String groupId                  // Unique identifier for group.  
    String description              // Brief text describing the group purposes.  

    @ManyToMany(mappedBy="groups")  
    @Cascade(SAVE_UPDATE)  
    List<User> users  

    ....  
}  

В базе данных: usertable (id, userId, name) групповая таблица (идентификатор, описание) группа пользователей (идентификатор пользователя, идентификатор группы, ключ группы)

Очень приятно добавлять группу в список групп, вызывать метод сохранения для пользователя и смотреть в спящем режиме сохранение пользовательской группы вместе. Однако у меня есть большая проблема, связанная с автоматическим удалением записи в спящем режиме из таблицы групп пользователей при извлечении пользователя после операции сохранения (пользователя).

Вот тестовая последовательность, которая генерирует удаление группы пользователей

  1. сохранить нового пользователя
  2. сохранить новую группу
  3. И группу к списку в пользователе
  4. сохранить пользователя
  5. получить пользователя из электронной почты
    @Test
    @Transactional
    public void testGetUserByEmail(){
        Session session = factory.getCurrentSession(); 

        String email = "sarah.silverman@comedycentral.com"; 
        User user = createUser(); 
        user.setWeCanContact(true); 
        user.setPartnersCanContact(false); 
        user.setAgreedTerms(false); 
        user.setReferer("Laura");

        String groupId = "AARP"; 
        String description = "Appletalk Address Resolution Protocol"; 
        Group group1 = new Group(); 
        group1.setGroupId(groupId); 
        group1.setDescription(description); 
        session.save(group1); 
        session.flush(); 
        user.getGroupLists().add(group1); 
        session.saveOrUpdate(user); 

        User testUser = userRepository.getUserByEmail(email);
        assertNotNull(testUser); 
        assertEquals("It's not the correct email", email, testUser.getEmail()); 
    }
    private User createUser(){
        Session session = factory.getCurrentSession(); 
        String userId = "UB:2010"; 
        String userPassword = "sarah"; 
        String realName = "Sarah Silverman"; 
        String email = "sarah.silverman@comedycentral.com"; 

        User user = new User();
        user.setUserId(userId); 
        user.setUserName(email); 
        user.setUserPassword(userPassword); 
        user.setRealName(realName); 
        user.setEmail(email); 

        List<Group> emptyGroupLists = new ArrayList<Group>(); 
        user.setGroupLists(emptyGroupLists); 
        Group group = new Group(); 
        group.setGroupId("ABC"); 
        group.setDescription("A for apple");
        user.getGroupLists().add(group);
        session.save(group); 
        session.save(user); 

        session.flush();
        return user; 
    }
// Repository Method to get user from email
// 
//  @NamedQuery(name="user.findByEmail",
//       query="SELECT u FROM User u " +
//    "LEFT JOIN FETCH u.groupLists " +
//              "WHERE upper(u.email) = :email")

public User getUserByEmail(String email) {
    Session session = sessionFactory.getCurrentSession(); 
    Query query = session.getNamedQuery("user.findByEmail");
    query.setParameter("email", email.toUpperCase());
    User user = (User)query.uniqueResult();
    return user; 
}

Перед выполнением шага 5, группа пользователей с автоматически удаляется как // вывод SQL

Hibernate:
delete
from
usergroup
where
userid=? 

Несколько вещей, которые я должен отметить; 1. ИД пользователя не является ПК пользователя. Будет ли это проблемой? 2. Отображение manyTomany в группе пользователей, сопоставленных по userid и groupid 3. Это происходит не только в тесте. Он тоже в разработке.

Как мне остановить автоматическое удаление группы пользователей. Группа пользователей является очень важной таблицей и не должна быть удалена. Любая помощь приветствуется. Спасибо.

1 Ответ

3 голосов
/ 18 января 2010

Посмотрим на пользователя

public class User {

    @Id
    @GeneratedValue
    private Integer id;

    @ManyToMany
    @JoinTable(name="USER_GROUP",  
        joinColumns=@JoinColumn(name="USER_ID", referencedColumnName="USER_ID"),
        inverseJoinColumns=@JoinColumn(name="GROUP_ID")
    )
    private List<Group> groupList = new ArrayList<Group>();

}

Теперь наша группа

public class Group {

    @Id
    private String id;

    @ManyToMany(mappedBy="groupList")
    @Cascade(SAVE_UPDATE)
    private List<User> userList = new ArrayList<User>();

}

Прежде чем продолжить, давайте рассмотрим поле userList в двух словах

// Group.java

@ManyToMany(mappedBy="groupList")
@Cascade(SAVE_UPDATE)
private List<User> userList = new ArrayList<User>();

@ Cascade (SAVE_UPDATE) означает

Сохранить или обновить каждого пользователя, на которого имеется ссылка

mappedBy = "groupList" означает

Для каждого пользователя REFERENCED посмотрите, есть ли у него ссылка на меня (объект группы). Если это так, установите наши двунаправленные отношения. Поэтому, если вы хотите связать пользователя и группу через таблицу USER_GROUP, каждый пользователь REFERENCED должен иметь ссылку на объект Group.

Теперь посмотрим, что происходит в методе testGetUserByEmail

Group group = new Group(); 
group.setId(groupId);

// group.getUserList(); returns a empty List, right ?
// As there is no User with reference to group in group.getUserList();
// So NO LINK between Group and User through USER_GROUP table
session.save(group);

// It explains why your link is missing
// You need to set up both sides
user.getGroupLists().add(group);

// Just save a User
// Nothing else
session.saveOrUpdate(user);

В методе createUser у вас тот же сценарий, который показан выше

Так что мой совет

При использовании двунаправленной связи ВСЕГДА используйте метод дополнительного удобства

// Group.java
public void addUser(User user) {
    user.getGroupList().add(this);

    getUserList().add(user);
}

// User.java
public void addGroup(Group group) {
    group.getUserList().add(this);

    getGroupList().add(group);
}

С уважением,

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