在不创建新对象的情况下将对象 A 中的对象添加到对象 B 中?休眠
Adding an object from Object A into Object B without creating new object ? HIBERNATE
假设我有两个对象,一个是用户对象,另一个是状态对象。 state 对象基本上是美国的 50 个州,所以它永远不需要改变。然而,用户对象有一个用户去过的国家的集合。所以像这样:
@Entity
@Table(name="tbl_users")
class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="id", unique=true, nullable = false)
private int id;
@Column(name="user_name")
private String name;
@OneToMany(targetEntity=State.class, orphanRemoval = false)
@Column(name="states")
private Collection<State> states;
//getters and setters
}
States 实体如下所示:
@Entity
@Table(name="tbl_states")
class State {
@Id
@Column(name="id", unique=true, nullable=false)
private int id;
@Column(name="state")
private String state;
// getters and setters
}
添加用户代码(使用hibernate):
public int addUser(User user) {
em.persist(user);
em.flush();
return user.getId();
}
通过id获取状态的代码:
public State getStateById(int id) {
return em.createQuery("SELECT s FROM State s WHERE s.id =:id, State.class)
.setParameter("id", id)
.getSingleResult();
}
但是当我尝试创建一个用户并选择几个状态时,我得到一个 PSQLException:
org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "uk_g6pr701i2pcq7400xrlb0hns"
2017-06-21T22:54:35.959991+00:00 app[web.1]: Detail: Key (states_id)=(5) already exists.
我尝试查找级联方法以查看是否可以使用任何方法,但 Cascade.MERGE 和 Cascade.PERSIST 似乎做同样的事情,其余的我认为我不需要 (删除、分离等)。我的问题是:
如何在不出现该错误的情况下向用户对象添加状态?
在您的情况下,最好使用多对多关联与多对多休眠不生成单一性约束。
Hibernate 自动生成方案的行为对于 onetoMany 有点奇怪,但您可以使用此解决方法。
试试这个:
@ManyToMany
@JoinTable(name = "user_state")
private List<State> states;
此代码有效:
class Example {
@Test
public void workingTest() {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("testPU");
EntityManager em = emf.createEntityManager();
// Creating three states
State alabama = new State(state: 'Alabama');
State louisiana = new State(state: 'Louisiana');
State texas = new State(state: 'Texas');
em.getTransaction().begin();
em.persist(alabama);
em.persist(louisiana);
em.persist(texas);
em.getTransaction().commit();
List<State> states = em.createQuery('FROM State').getResultList();
// Assert only three states on DB
assert states.size() == 3;
User userFromAlabama = new User();
User userFromAlabamaAndTexas = new User();
em.getTransaction().begin();
State alabamaFromDB = em.find(State, alabama.getId());
State texasFromDB = em.find(State, texas.getId());
userFromAlabama.getStates().add(alabamaFromDB);
userFromAlabamaAndTexas.getStates().add(alabamaFromDB);
userFromAlabamaAndTexas.getStates().add(texasFromDB);
em.persist(userFromAlabama);
em.persist(userFromAlabamaAndTexas);
em.getTransaction().commit();
states = em.createQuery('FROM State').getResultList();
// Assert only three states on DB again
assert states.size() == 3;
// Assert one user
User userFromDB = em.find(User, userFromAlabama.getId());
assert userFromDB.getStates().size() == 1;
userFromDB = em.find(User, userFromAlabamaAndTexas.getId());
assert userFromDB.getStates().size() == 2;
}
}
@Entity
@Table(name="tbl_users")
class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id
@Column(name="user_name")
private String name
@ManyToMany
private Collection<State> states = Lists.newArrayList()
// Getters and setters
}
@Entity
@Table(name="tbl_states")
class State {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Column(name="state")
private String state;
// Getters and setters
}
您应该将映射更改为@ManyToMany!
并且您必须在 DB 上有 3 个 table,如下所示:
TBL_USERS、TBL_STATES 和 TBL_USERS_TBL_STATES
TBL_USERS_TBL_STATES table 是 Hibernate 在使用 @ManyToMany 注释 属性 时使用的默认 table 名称。如果要更改 TBL_USERS_TBL_STATES 的 tablename,也请使用 @JoinTable 注释。请参阅文档 here
使用此配置,您应该能够从数据库中获取状态,将其添加到新用户,然后保存它。我进行了单元测试并且它有效!
假设我有两个对象,一个是用户对象,另一个是状态对象。 state 对象基本上是美国的 50 个州,所以它永远不需要改变。然而,用户对象有一个用户去过的国家的集合。所以像这样:
@Entity
@Table(name="tbl_users")
class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="id", unique=true, nullable = false)
private int id;
@Column(name="user_name")
private String name;
@OneToMany(targetEntity=State.class, orphanRemoval = false)
@Column(name="states")
private Collection<State> states;
//getters and setters
}
States 实体如下所示:
@Entity
@Table(name="tbl_states")
class State {
@Id
@Column(name="id", unique=true, nullable=false)
private int id;
@Column(name="state")
private String state;
// getters and setters
}
添加用户代码(使用hibernate):
public int addUser(User user) {
em.persist(user);
em.flush();
return user.getId();
}
通过id获取状态的代码:
public State getStateById(int id) {
return em.createQuery("SELECT s FROM State s WHERE s.id =:id, State.class)
.setParameter("id", id)
.getSingleResult();
}
但是当我尝试创建一个用户并选择几个状态时,我得到一个 PSQLException:
org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "uk_g6pr701i2pcq7400xrlb0hns"
2017-06-21T22:54:35.959991+00:00 app[web.1]: Detail: Key (states_id)=(5) already exists.
我尝试查找级联方法以查看是否可以使用任何方法,但 Cascade.MERGE 和 Cascade.PERSIST 似乎做同样的事情,其余的我认为我不需要 (删除、分离等)。我的问题是: 如何在不出现该错误的情况下向用户对象添加状态?
在您的情况下,最好使用多对多关联与多对多休眠不生成单一性约束。
Hibernate 自动生成方案的行为对于 onetoMany 有点奇怪,但您可以使用此解决方法。
试试这个:
@ManyToMany
@JoinTable(name = "user_state")
private List<State> states;
此代码有效:
class Example {
@Test
public void workingTest() {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("testPU");
EntityManager em = emf.createEntityManager();
// Creating three states
State alabama = new State(state: 'Alabama');
State louisiana = new State(state: 'Louisiana');
State texas = new State(state: 'Texas');
em.getTransaction().begin();
em.persist(alabama);
em.persist(louisiana);
em.persist(texas);
em.getTransaction().commit();
List<State> states = em.createQuery('FROM State').getResultList();
// Assert only three states on DB
assert states.size() == 3;
User userFromAlabama = new User();
User userFromAlabamaAndTexas = new User();
em.getTransaction().begin();
State alabamaFromDB = em.find(State, alabama.getId());
State texasFromDB = em.find(State, texas.getId());
userFromAlabama.getStates().add(alabamaFromDB);
userFromAlabamaAndTexas.getStates().add(alabamaFromDB);
userFromAlabamaAndTexas.getStates().add(texasFromDB);
em.persist(userFromAlabama);
em.persist(userFromAlabamaAndTexas);
em.getTransaction().commit();
states = em.createQuery('FROM State').getResultList();
// Assert only three states on DB again
assert states.size() == 3;
// Assert one user
User userFromDB = em.find(User, userFromAlabama.getId());
assert userFromDB.getStates().size() == 1;
userFromDB = em.find(User, userFromAlabamaAndTexas.getId());
assert userFromDB.getStates().size() == 2;
}
}
@Entity
@Table(name="tbl_users")
class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id
@Column(name="user_name")
private String name
@ManyToMany
private Collection<State> states = Lists.newArrayList()
// Getters and setters
}
@Entity
@Table(name="tbl_states")
class State {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Column(name="state")
private String state;
// Getters and setters
}
您应该将映射更改为@ManyToMany!
并且您必须在 DB 上有 3 个 table,如下所示: TBL_USERS、TBL_STATES 和 TBL_USERS_TBL_STATES
TBL_USERS_TBL_STATES table 是 Hibernate 在使用 @ManyToMany 注释 属性 时使用的默认 table 名称。如果要更改 TBL_USERS_TBL_STATES 的 tablename,也请使用 @JoinTable 注释。请参阅文档 here
使用此配置,您应该能够从数据库中获取状态,将其添加到新用户,然后保存它。我进行了单元测试并且它有效!