Я активно изучаю JPA и EJB, и я пришел к следующей ситуации: у меня есть один EJB (называемый SecondController
), который реализует метод для сохранения сущности. Позвольте назвать его SecondEntity
. Существует требование, чтобы, когда объект сохраняется, его поле dateInserted
устанавливается на текущую дату (на практике требования могут быть более сложными - я хочу знать, является ли концепция в порядке или если я пойду полностью в неправильном направлении).
Теперь я определяю новый объект - позволю ему FirstEntity
который содержит SecondEntity
как атрибут. Я реализую еще один EJB, который реализует метод для сохранения FirstEntity
- поэтому каждый раз, когда FirstEntity
сохраняется, SecondEntity
также сохраняется. Я знаю, что могу использовать @ManyToOne(optional = false, cascade = CascadeType.PERSIST)
на secondEntity
атрибута в FirstEntity
(что будет делать автоматически сохраняются). Но помните, что есть требование dateInserted
и логика уже реализована. Идея состоит в том, чтобы повторно использовать уже реализованный метод для сохранения SecondEntity
в SecondController
, введя его в FirstController
.
@Entity
public class SecondEntity implements Serializable
{
}
@Entity
public class FirstEntity implements Serializable
{
@JoinColumn(name = "second_id", referencedColumnName = "second_id")
@ManyToOne(optional = false)
private SecondEntity secondEntity;
}
@Stateless
public class SecondController implements Serializable
{
@PersistenceUnit(name = "PU")
private EntityManagerFactory emf;
public SecondController()
{
}
public void create(SecondEntity secondEntity)
{
EntityManager em = emf.createEntityManager();
try
{
secondEntity.setDateInserted(new Date(System.currentTimeMillis()));
em.persist(secondEntity);
}
finally
{
em.close();
}
}
}
@Stateless
public class FirstController implements Serializable
{
@PersistenceUnit(name = "PU")
private EntityManagerFactory emf;
@EJB
private SecondController secondController;
public FirstController()
{
}
public void create(FirstEntity firstEntity)
{
EntityManager em = emf.createEntityManager();
try
{
secondController.create(firstEntity.getSecondEntity());
em.persist(firstEntity);
}
finally
{
em.close();
}
}
}
Точка примерного кода выше - вызов secondController.create(firstEntity.getSecondEntity())
. Это нормально или считается плохой практикой? У меня есть два таких случая в моем приложении, и один работает (SecondEntity
является необязательным - может быть null
), а тот, который не имеет значения (SecondEntity
является обязательным - не может быть null
). Код не работает в em.persist(firstEntity)
, говоря:
java.lang.IllegalStateException: во время синхронизации новый объект был найден через отношение, которое не было отмечено каскадом PERSIST
Если я заменю упомянутый вызов на em.persist(firstEntity.getSecondEntity)
код работает нормально.
Как я могу решить эту проблему?
Вы не должны устанавливать поле dateInserted
в своем EJB. Сделайте это в случае с событием PrePersist
. Таким образом, поставщик персистентности будет уверен, что ваш крючок всегда вызывается автоматически перед сохранением объекта. Затем вы можете позволить persist быть каскадом от родительского объекта к другому (@ManyToOne(optional = false, cascade = CascadeType.PERSIST)
).
@Entity
public class SecondEntity implements Serializable {
@PrePersist
public void prePersist() {
if (dateInserted == null) {
dateInserted = new Date();
}
}
}