Reputation: 79
I have the bidirectional OneToOne association Account <-> Budget
.
According to this I tried to lazily load the association:
For the Account.java
:
@Audited
@Entity
public class Account {
@Id
@GeneratedValue(strategy = GenerationType.TABLE)
protected long id;
@OneToOne(mappedBy = "account", cascade = CascadeType.ALL, orphanRemoval=true, fetch=FetchType.LAZY)
private Budget mainBudget;
}
...
}
For the Budget.java
:
@Audited
@Entity
public class Budget {
@Id
@GeneratedValue(strategy = GenerationType.TABLE)
protected long id;
@OneToOne(fetch=FetchType.LAZY)
@MapsId
private Account account;
@OneToMany(targetEntity = Budget.class, cascade = CascadeType.ALL,
mappedBy = "parentBudget", orphanRemoval=true)
@Fetch(value = FetchMode.SUBSELECT)
private List<Budget> subBudget;
...
}
Now I am trying to make a new account with a new budget with the create
-method in the DAOClass looking as follows:
@Resource(name = "DBRouter", type = DatabaseRouter.class)
protected DatabaseRouter router;
@PersistenceContext
protected EntityManager em;
@Transactional
public D create(D d, boolean flush, String resource) {
router.setDataSource(resource);
if (flush) {
em.flush();
}
D obj = em.merge(d);
if (flush) {
em.flush();
}
return obj;
}
This gives me the following exception:
javax.persistence.EntityExistsException: A different object with the same identifier value was already associated with the session : [[PACKACKENAMES].Account#50](31 internal lines)
at org.apache.openejb.persistence.JtaEntityManager.merge(JtaEntityManager.java:203)
at [PACKACKENAMES].DAOClass.create(DaoClass.java:75)
at [PACKACKENAMES].DaoClass.create(DaoClass.java:66)
...
If I remove the @MapsId
annotation, then I don't have this problem, although then the lazy loading does not work properly. What is the reason for this exception and how to solve it?
Upvotes: 0
Views: 182
Reputation: 4303
You have:
public class Budget {
@Id
@GeneratedValue(strategy = GenerationType.TABLE)
protected long id;
@OneToOne(fetch=FetchType.LAZY)
@MapsId
private Account account;
But this mapping doesn't make sense. The id
can't be a @GeneratedValue
if it's mapped by the one-to-one association to Account
.
So:
@GeneratedValue
annotation, and alsoid
field to the value of the id
field of the associated Account
.Or, alternatively:
@MapsId
, if what you want is a foreign key column that is separate from the primary key.See also:
Hibernate error (EntityExistsException) when persisting entity with children multiple times
Which is a similar problem.
Upvotes: 0
Reputation: 4858
In your case Account is a parent entity for Budget. @MapsId annotation says JPA to use the id of the parent entity for the mapping of annotated one-to-one relationship. Both ids will be identical for associated entities (rows). There is no need to generate a separate id for Budget. As we can see from the exception it would even not work.
Solution - remove the @GeneratedValue annotation from the Budget entity.
public class Budget {
@Id
private long id;
@OneToOne(fetch=FetchType.LAZY)
@MapsId
private Account account;
...
}
Upvotes: 1