] У меня возникла проблема с ассоциацией многие ко многим на уровне персистентности. Мой сценарий следующий: [
] [] У пользователя может быть несколько ролей, и к роли может быть прикреплено несколько пользователей. Во время тестов я столкнулся со странным поведением. Я создал объект роли и несколько объектов пользователя. Каждому из пользователей была назначена роль. После этого пользователи были сохранены с помощью DAO. Затем загружается один из пользователей, чтобы проверить, получил ли он переданную ему роль перед сохранением объекта пользователя. Вызов [] getRoles () [
] для пользователя показывает, что роль была установлена правильно. [
] Чтобы проверить, работает ли обратное направление, объект роли загружается из базы данных с помощью роли DAO. Но вызов [] getUsers () [
] для объекта роли просто возвращает пустой набор, хотя он должен содержать всех пользователей с этой ролью. [
] Я дважды проверил таблицу базы данных, но вроде все в порядке. Таблица User, role и user_role были заполнены правильно. [
] [] [] Так почему же объект роли не содержит пользователя? [] [
] [] Я использую Hibernate и Spring со следующими классами. [
] [] [] Класс пользователя [] [
] [@Entity
@Table
public class User extends BusinessObject {
...
// Option 1
@ManyToMany(fetch = FetchType.LAZY,
cascade = CascadeType.ALL,
targetEntity=Role.class)
@JoinTable(name= "user_role",
joinColumns = {@JoinColumn(name="user_id")},
inverseJoinColumns = {@JoinColumn(name="role_id")})
// Option 2
@ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinTable(name= "user_role",
joinColumns = {@JoinColumn(name="user_id")},
inverseJoinColumns = {@JoinColumn(name="role_id")})
private Set<Role> roles = new HashSet<Role>();
...
}
]
[] [] Ролевой класс [] [
] [@Entity
@Table
public class Role extends BusinessObject {
...
// Option 1
@ManyToMany(fetch = FetchType.LAZY,
cascade = CascadeType.ALL,
mappedBy= "roles",
targetEntity = User.class)
// Option 2
@ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinTable(name= "user_role",
joinColumns = {@JoinColumn(name="role_id")},
inverseJoinColumns = {@JoinColumn(name="user_id")})
private Set<User> users = new HashSet<User>();
...
}
]
[] Для тестирования я использую следующий код в тестовом классе JUnit. [
] [@Test
public void test(){
Transaction trans = sessionFactory.getCurrentSession().beginTransaction();
Role userAdminRole = new Role();
userAdminRole.setName(RoleName.USER_ADMIN);
Role userRole = new Role();
userRole.setName(RoleName.USER);
User user1 = new User();
user1.setEmail("user1@user.de");
user1.getRoles().add(userAdminRole);
user1.getRoles().add(userRole);
userDao.save(user1);
User user2 = new User();
user2.setEmail("user2@user.de");
user2.getRoles().add(role);
userDao.save(user2);
User user3 = new User();
user3.setEmail("user3@user.de");
user3.getRoles().add(role);
userDao.save(user3);
trans.commit();
User loadedUser = userDao.load(user1.getId());
// Tests passes
Assert.assertNotNull(loadedUser);
Assert.assertEquals(user1, loadedUser);
Set<Role> roles = loadedUser.getRoles();
// Tests passes
Assert.assertEquals(2, roles.size());
Role loadedUserAdminRole = roleDao.findByName(RoleName.USER_ADMIN);
Set<User> users = loadedUserAdminRole.getUsers();
// Test fails: Count is 0 instead of 3 !!!!!!!
Assert.assertEquals(3, users.size());
}
]
[] [] ОБНОВЛЕНИЕ [] [
] [] Извините, я забыл упомянуть одну вещь. Когда я тестировал код, я, конечно, не отмечал ассоциацию многие ко многим дважды в каждом файле класса. Вместо этого я использовал либо вариант 1, либо вариант 2 в каждом файле класса. [
]