m//
оператор имеет некоторые неясные особые случаи:
?
в качестве разделителя, он только соответствует однажды, если Вы не звоните reset
. '
в качестве разделителя, шаблон не интерполирован. У вас уже есть несколько хороших ответов о том, как сделать именно то, что вы просите ..
Для справки позвольте мне просто упомянуть рекомендуемый способ сделать это в Hibernate, который - использовать суррогатный ключ в качестве первичного ключа и отмечать бизнес-ключи как NaturalId:
Хотя мы рекомендуем использовать суррогатные ключи в качестве первичных ключей, вы следует попытаться определить естественные ключи для всех сущностей. Естественный ключ - это собственность или комбинация свойств который уникален и не равен нулю. это также неизменный. Сопоставьте свойства естественный ключ внутри элемент. Hibernate будет сгенерировать необходимый уникальный ключ и ограничения допустимости значений NULL и, как результат, ваше отображение будет больше самодокументируемый.
Рекомендуется реализовать equals () и hashCode () для сравнения естественные ключевые свойства объекта.
В коде, использующем аннотации, это будет выглядеть примерно так:
@Entity
public class UserRole {
@Id
@GeneratedValue
private long id;
@NaturalId
private User user;
@NaturalId
private Role role;
}
Использование этого избавит вас от многих головных болей в будущем, поскольку вы узнаете, когда вам часто приходится ссылка / сопоставление составного первичного ключа.
Я обнаружил это на собственном горьком опыте и в конце концов просто отказался от борьбы с Hibernate и вместо этого решил плыть по течению. Я полностью понимаю, что в вашем случае это может быть невозможно, поскольку вы имеете дело с устаревшим программным обеспечением или зависимостями, но я просто хотел упомянуть об этом для справки в будущем. ( если вы не можете его использовать, возможно, кто-то другой может !)
Спасибо, что улучшили свой вопрос ... и приняли во внимание предложения.
(Извините, это немного странно, что вы прикрепляете свои сущности к Даосу, но это не точка.)
Я не уверен, что осталась какая-то проблема:
Составные ключи создаются с использованием @IdClass (другой способ - использовать @EmbeddedId и @Embeddable, не знаю, какой из них вы ищете) @IdClass выглядит следующим образом
@Entity
@IdClass(CategoryPK.class)
public class Category {
@Id
protected String name;
@Id
protected Date createDate;
}
public class CategoryPK implements Serializable {
String name;
Date createDate;
public boolean equals(object other) {
//implement a equals that the PP can use to determine
//how the CategoryPK object can be identified.
}
public int hashCode(){
return Super.hashCode();
}
}
моя Категория здесь будет быть вашими user_roles, а имя и createDate будут вашими идентификаторами пользователя и ролью
Чтобы выполнить ваше требование, вы можете сопоставить свой @ManyToMany как сопоставление @OneToMany. Таким образом, USER_ROLE будет содержать как USER_ID, так и ROLE_ID в качестве составного первичного ключа
. Я покажу вам, как:
@Entity
@Table(name="USER")
public class User {
@Id
@GeneratedValue
private Integer id;
@OneToMany(cascade=CascadeType.ALL, mappedBy="joinedUserRoleId.user")
private List<JoinedUserRole> joinedUserRoleList = new ArrayList<JoinedUserRole>();
// no-arg required constructor
public User() {}
public User(Integer id) {
this.id = id;
}
// addRole sets up bidirectional relationship
public void addRole(Role role) {
// Notice a JoinedUserRole object
JoinedUserRole joinedUserRole = new JoinedUserRole(new JoinedUserRole.JoinedUserRoleId(this, role));
joinedUserRole.setUser(this);
joinedUserRole.setRole(role);
joinedUserRoleList.add(joinedUserRole);
}
}
@Entity
@Table(name="USER_ROLE")
public class JoinedUserRole {
public JoinedUserRole() {}
public JoinedUserRole(JoinedUserRoleId joinedUserRoleId) {
this.joinedUserRoleId = joinedUserRoleId;
}
@ManyToOne
@JoinColumn(name="USER_ID", insertable=false, updatable=false)
private User user;
@ManyToOne
@JoinColumn(name="ROLE_ID", insertable=false, updatable=false)
private Role role;
@EmbeddedId
// Implemented as static class - see bellow
private JoinedUserRoleId joinedUserRoleId;
// required because JoinedUserRole contains composite id
@Embeddable
public static class JoinedUserRoleId implements Serializable {
@ManyToOne
@JoinColumn(name="USER_ID")
private User user;
@ManyToOne
@JoinColumn(name="ROLE_ID")
private Role role;
// required no arg constructor
public JoinedUserRoleId() {}
public JoinedUserRoleId(User user, Role role) {
this.user = user;
this.role = role;
}
public JoinedUserRoleId(Integer userId, Integer roleId) {
this(new User(userId), new Role(roleId));
}
@Override
public boolean equals(Object instance) {
if (instance == null)
return false;
if (!(instance instanceof JoinedUserRoleId))
return false;
final JoinedUserRoleId other = (JoinedUserRoleId) instance;
if (!(user.getId().equals(other.getUser().getId())))
return false;
if (!(role.getId().equals(other.getRole().getId())))
return false;
return true;
}
@Override
public int hashCode() {
int hash = 7;
hash = 47 * hash + (this.user != null ? this.user.hashCode() : 0);
hash = 47 * hash + (this.role != null ? this.role.hashCode() : 0);
return hash;
}
}
}
запомнить
Если объекту назначен идентификатор или составной ключ, идентификатор ДОЛЖЕН БЫТЬ НАЗНАЧЕН экземпляр объекта ПЕРЕД вызовом save ().
Итак, мы создали конструктор JoinedUserRoleId, подобный этому, чтобы позаботиться о нем
public JoinedUserRoleId(User user, Role role) {
this.user = user;
this.role = role;
}
И, наконец, класс роли
@Entity
@Table(name="ROLE")
public class Role {
@Id
@GeneratedValue
private Integer id;
@OneToMany(cascade=CascadeType.ALL, mappedBy="JoinedUserRoleId.role")
private List<JoinedUserRole> joinedUserRoleList = new ArrayList<JoinedUserRole>();
// no-arg required constructor
public Role() {}
public Role(Integer id) {
this.id = id;
}
// addUser sets up bidirectional relationship
public void addUser(User user) {
// Notice a JoinedUserRole object
JoinedUserRole joinedUserRole = new JoinedUserRole(new JoinedUserRole.JoinedUserRoleId(user, this));
joinedUserRole.setUser(user);
joinedUserRole.setRole(this);
joinedUserRoleList.add(joinedUserRole);
}
}
В соответствии с его проверкой, давайте напишем следующее
User user = new User();
Role role = new Role();
// code in order to save a User and a Role
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
Serializable userId = session.save(user);
Serializable roleId = session.save(role);
session.getTransaction().commit();
session.clear();
session.close();
// code in order to set up bidirectional relationship
Session anotherSession = HibernateUtil.getSessionFactory().openSession();
anotherSession.beginTransaction();
User savedUser = (User) anotherSession.load(User.class, userId);
Role savedRole = (Role) anotherSession.load(Role.class, roleId);
// Automatic dirty checking
// It will set up bidirectional relationship
savedUser.addRole(savedRole);
anotherSession.getTransaction().commit();
anotherSession.clear();
anotherSession.close();
Уведомление в соответствии с приведенным выше кодом НИКАКОЙ ССЫЛКИ на класс JoinedUserRole.
Если вы хотите получить роль JoinedUserRole, попробуйте следующее
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
Integer userId;
Integer roleId;
// Lets say you have set up both userId and roleId
JoinedUserRole joinedUserRole = (JoinedUserRole) session.get(JoinedUserRole.class, new JoinedUserRole.JoinedUserRoleId(userId, roleId));
// some operations
session.getTransaction().commit();
session.clear();
session.close();
с уважением,