I have two entities: Question and FavoritesCounter. FavoritesCounter should be created when the question is added to favorites for the first time.
Consider a use case when two users tries to add a question to favorites simultaneously - this will cause EntityExistsException
when entityManager.persist(counter)
is called for the second user.
But the code below doesn't work, because when EntityExistsException
is thrown, container marks transaction as rollback only and attempt to return getFavoritesCounter(question)
fails with javax.resource.ResourceException: Transaction is not active
@Stateless
public class FavoritesServiceBean implements FavoritesService {
...
public void addToFavorites(Question question) {
FavoritesCounter counter = getCounter(question);
if (counter == null) {
counter = createCounter(question);
}
//increase counter
}
private FavoritesCounter createCounter(Question question) {
try {
FavoritesCounter counter = new FavoritesCounter();
counter.setQuestion(question);
entityManager.persist(counter);
entityManager.flush();
return counter;
} catch (EntityExistsException e) {
return getFavoritesCounter(question);
}
}
private FavoritesCounter getFavoritesCounter(Question question) {
Query counterQuery = entityManager.createQery("SELECT counter FROM FavoritesCounter counter WHERE counter.question = :question");
counterQuery.setParameter("question", question);
List<FavoritesCounter> result = counterQuery.getResultList();
if (result.isEmpty()) return null;
return result.get(0);
}
}
Question
@Entity
public class Question implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
//getter and setter for id
}
FavoritesCounter
@Entity
public class FavoritesCounter implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@OneToOne
@Column(unique = true)
private Question question;
//getter and setter
}
What is the best way to return already created entity after EntityExistsException
?