请忍受这个长期问题,这是一个难以描述的困难局面。
我们正在看到我只能通过JPA applcation将我们描述为神秘级联更新到我们的数据库。该应用程序是批处理器。我们有三个具有这种关系的表/实体:
ObjectA has one to many on ObjectB
ObjectB has one to many on ObjectC
其中ObjectA是批处理对象,ObjectB是一个容器对象,它包含实际需要处理的ObjectC。我们在第一个ObjectB中处理ObjectC,然后在第二个ObjectB等中处理ObjectC。在处理过程中,只有ObjectA和ObjectC的实例在数据库中实际更新。
我们通过执行命名查询而不是遵循关系来获取ObjectC列表,因为它们需要被过滤。
ObjectA&#39>状态在处理开始时和结束时更新。 ObjectCs'状态在处理时会更新。
我们看到ObjectC的状态再次更新为先前(错误)状态,但无法确定我们调用更新的内容。起初我以为它是从ObjectA的状态更新级联起来的,所以我改变了实体类的级联类型,只改为持久化并且不更新。它们看起来像这样:
@Entity
@Table(name = "OBJECT_A")
@Cacheable(false)
public class ObjectA implements Serializable
{
// bi-directional many-to-one association to OpticalReceiver
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST, mappedBy = "objectA")
private Set<ObjectB> objectBs;
....
}
@Entity
@Table(name = "OBJECT_b")
@Cacheable(false)
public class ObjectB implements Serializable
{
// bi-directional many-to-one association to OpticalReceiver
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST, mappedBy = "objectB")
private List<ObjectC> objectCs;
// bi-directional many-to-one association to Batch
@ManyToOne
@JoinColumn(name = "ID", nullable = false, insertable = false, updatable = false)
private ObjectA objectA;
...
}
@Entity
@Table(name = "OBJECT_b")
@Cacheable(false)
public class ObjectB implements Serializable
{
// bi-directional many-to-one association to OpticalReceiver
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST, mappedBy = objectB")
private List<ObjectC> objectCs;
// bi-directional many-to-one association to Batch
@ManyToOne
@JoinColumn(name = "ID", nullable = false, insertable = false, updatable = false)
private ObjectA objectA;
...
}
但是,我们仍在获取更新。我添加了日志记录到我们的DataService类以查看它何时被调用。最初,我有一个堆栈跟踪,但是当&#34; mystery&#34;时,不会调用更新和创建方法。更新发生。它看起来像这样:
在我的数据服务对象中,我有以下方法:
public class DataService implements GenericService
{
private final Logger logger = LoggerFactory.getLogger(DataService.class);
@PersistenceContext(unitName = "database")
private EntityManager em;
@Override
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public <T> T create(T t)
throws IllegalArgumentException, EntityExistsException, PersistenceException
{
em.persist(t);
logger.debug("Persisted objectType={} ({}) to database (Batch should cascade)", t.getClass().getSimpleName(), t);
return t;
}
@Override
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public <T> T update(T t)
throws IllegalArgumentException, PersistenceException
{
t = em.merge(t);
logger.debug("Updated objectType={} ({}) to database (Batch should NOT cascade)", t.getClass().getSimpleName(), t);
return t;
}
...
}
我们只看到更新并在预期时创建方法记录。我们没有看到他们被称为神秘更新声明。但是我们确实在server.log文件中看到了SQL语句(在JBoss EAP中使用EclipsLink):
08:54:14,610 (EJB default - 6) UPDATE OBJECT_C SET CURRENT_STATE = ? WHERE ((ID = ?) AND (CHANGE_ID = ?))[2, 00:11:80:8d:71:be, CRQ000000000001]
08:54:19,283 (EJB default - 6) UPDATE OBJECT_C SET CURRENT_STATE = ? WHERE ((ID = ?) AND (CHANGE_ID = ?))[6, 00:11:80:8d:71:be, CRQ000000000001]
08:54:24,180 (EJB default - 7) UPDATE OBJECT_C SET CURRENT_STATE = ? WHERE ((ID = ?) AND (CHANGE_ID = ?))[2, 00:15:2f:2c:4d:f2, CRQ000000000001]
08:54:25,140 (EJB default - 7) UPDATE OBJECT_C SET CURRENT_STATE = ? WHERE ((ID = ?) AND (CHANGE_ID = ?))[6, 00:15:2f:2c:4d:f2, CRQ000000000001]
08:54:34,192 (EJB default - 8) UPDATE OBJECT_C SET CURRENT_STATE = ? WHERE ((ID = ?) AND (CHANGE_ID = ?))[2, 00:15:2f:53:c7:3a, CRQ000000000001]
08:54:35,115 (EJB default - 8) UPDATE OBJECT_C SET CURRENT_STATE = ? WHERE ((ID = ?) AND (CHANGE_ID = ?))[6, 00:15:2f:53:c7:3a, CRQ000000000001]
08:54:44,199 (EJB default - 9) UPDATE OBJECT_C SET CURRENT_STATE = ? WHERE ((ID = ?) AND (CHANGE_ID = ?))[2, 00:15:a4:ac:31:03, CRQ000000000001]
08:54:45,168 (EJB default - 9) UPDATE OBJECT_C SET CURRENT_STATE = ? WHERE ((ID = ?) AND (CHANGE_ID = ?))[6, 00:15:a4:ac:31:03, CRQ000000000001]
08:54:54,207 (EJB default - 10) UPDATE OBJECT_C SET CURRENT_STATE = ? WHERE ((ID = ?) AND (CHANGE_ID = ?))[2, 00:15:cf:09:1a:69, CRQ000000000001]
08:54:55,327 (EJB default - 10) UPDATE OBJECT_C SET CURRENT_STATE = ? WHERE ((ID = ?) AND (CHANGE_ID = ?))[6, 00:15:cf:09:1a:69, CRQ000000000001]
08:55:04,222 (EJB default - 1) UPDATE OBJECT_C SET CURRENT_STATE = ? WHERE ((ID = ?) AND (CHANGE_ID = ?))[2, 00:15:cf:1b:4f:33, CRQ000000000001]
08:55:04,802 (EJB default - 1) UPDATE OBJECT_C SET CURRENT_STATE = ? WHERE ((ID = ?) AND (CHANGE_ID = ?))[6, 00:15:cf:1b:4f:33, CRQ000000000001]
08:55:14,220 (EJB default - 2) UPDATE OBJECT_C SET CURRENT_STATE = ? WHERE ((ID = ?) AND (CHANGE_ID = ?))[2, 00:1d:ce:62:00:f6, CRQ000000000001]
08:55:15,876 (EJB default - 2) UPDATE OBJECT_C SET CURRENT_STATE = ? WHERE ((ID = ?) AND (CHANGE_ID = ?))[6, 00:1d:ce:62:00:f6, CRQ000000000001]
08:55:24,227 (EJB default - 4) UPDATE OBJECT_C SET CURRENT_STATE = ? WHERE ((ID = ?) AND (CHANGE_ID = ?))[2, 00:1d:d1:ed:64:09, CRQ000000000001]
08:55:24,814 (EJB default - 4) UPDATE OBJECT_C SET CURRENT_STATE = ? WHERE ((ID = ?) AND (CHANGE_ID = ?))[6, 00:1d:d1:ed:64:09, CRQ000000000001]
08:55:34,237 (EJB default - 3) UPDATE OBJECT_C SET CURRENT_STATE = ? WHERE ((ID = ?) AND (CHANGE_ID = ?))[2, 5c:57:1a:5f:11:d3, CRQ000000000001]
08:55:34,237 (EJB default - 5) UPDATE OBJECT_C SET CURRENT_STATE = ? WHERE ((ID = ?) AND (CHANGE_ID = ?))[2, 00:11:80:8d:71:be, CRQ000000000001]
08:55:34,240 (EJB default - 5) UPDATE OBJECT_C SET CURRENT_STATE = ? WHERE ((ID = ?) AND (CHANGE_ID = ?))[2, 00:15:2f:2c:4d:f2, CRQ000000000001]
08:55:34,242 (EJB default - 5) UPDATE OBJECT_C SET CURRENT_STATE = ? WHERE ((ID = ?) AND (CHANGE_ID = ?))[2, 00:15:2f:53:c7:3a, CRQ000000000001]
08:55:34,245 (EJB default - 5) UPDATE OBJECT_C SET CURRENT_STATE = ? WHERE ((ID = ?) AND (CHANGE_ID = ?))[2, 00:15:a4:ac:31:03, CRQ000000000001]
08:55:34,247 (EJB default - 5) UPDATE OBJECT_C SET CURRENT_STATE = ? WHERE ((ID = ?) AND (CHANGE_ID = ?))[2, 00:15:cf:09:1a:69, CRQ000000000001]
08:55:34,250 (EJB default - 5) UPDATE OBJECT_C SET CURRENT_STATE = ? WHERE ((ID = ?) AND (CHANGE_ID = ?))[2, 00:15:cf:1b:4f:33, CRQ000000000001]
08:55:34,252 (EJB default - 5) UPDATE OBJECT_C SET CURRENT_STATE = ? WHERE ((ID = ?) AND (CHANGE_ID = ?))[2, 00:1d:ce:62:00:f6, CRQ000000000001]
08:55:34,255 (EJB default - 5) UPDATE OBJECT_C SET CURRENT_STATE = ? WHERE ((ID = ?) AND (CHANGE_ID = ?))[2, 00:1d:d1:ed:64:09, CRQ000000000001]
08:55:34,257 (EJB default - 5) UPDATE OBJECT_C SET CURRENT_STATE = ? WHERE ((ID = ?) AND (CHANGE_ID = ?))[2, 5c:57:1a:5f:11:d3, CRQ000000000001]
08:55:35,161 (EJB default - 3) UPDATE OBJECT_C SET CURRENT_STATE = ? WHERE ((ID = ?) AND (CHANGE_ID = ?))[6, 5c:57:1a:5f:11:d3, CRQ000000000001]
线程(EJB default - 5)
的更新是运行批处理的主要BatchProcessor线程。其他线程是为无法单独处理每个ObjectC而创建的无状态会话bean。
因此,主线程正在处理神秘更新。我们认为最终的ObjectA更新完成后可能会级联(即使CascadeType没有设置),因此取消了对它的调用。但是,ObjectC更新仍然会发生。
有没有人对如何确定触发这些更新的内容和/或如何阻止它们有任何建议?