我遇到过一种情况(我觉得很奇怪,但可能很正常),我使用EntityManager.getReference(LObj.getClass(),LObj.getId())获取数据库实体,然后将返回的对象传递给坚持在另一张桌子上.
所以基本上流程是这样的:
class TFacade{
createT(FObj, AObj) {
T TObj = new T();
TObj.setF(FObj);
TObj.setA(AObj);
...
EntityManager.persist(TObj);
...
L LObj = A.getL();
FObj.setL(LObj);
FFacade.editF(FObj);
}
}
@TransactionAttributeType.REQUIRES_NEW
class FFacade{
editF(FObj){
L LObj = FObj.getL();
LObj = EntityManager.getReference(LObj.getClass(), LObj.getId());
...
EntityManager.merge(FObj);
...
FLHFacade.create(FObj, LObj);
}
}
@TransactionAttributeType.REQUIRED
class FLHFacade{
createFLH(FObj, LObj){
FLH FLHObj = new FLH();
FLHObj.setF(FObj);
FLHObj.setL(LObj);
....
EntityManager.persist(FLHObj);
...
}
}
我得到以下异常"java.lang.IllegalArgumentException:未知实体:com.my.persistence.L $$ EnhancerByCGLIB $$ 3e7987d0"
在查看了一段时间之后,我终于想通了,因为我正在使用EntityManager.getReference()方法,因为该方法正在返回代理,所以我得到了上述异常.
这让我想知道,何时建议使用EntityManager.getReference()方法而不是EntityManager.find()方法?
如果EntityManager.getReference()无法找到正在搜索的实体本身非常方便,则会抛出EntityNotFoundException.如果EntityManager.find()方法无法找到实体,则它仅返回null.
关于事务边界,听起来像你需要在将新发现的实体传递给新事务之前使用find()方法.如果你使用getReference()方法,那么你可能会遇到类似我的情况,但有上述异常.
我读到这getOne()是懒惰加载并立即findOne()获取整个实体.我检查调试日志,我甚至能监视我的SQL服务器上看到被执行什么语句,我发现,无论getOne()和findOne()生成和执行相同的查询.但是当我使用时,getOne()这些值最初为null(当然除了id).
那么有人可以告诉我,如果两种方法在数据库上执行相同的查询,为什么我要使用一个而不是另一个?我基本上是在寻找一种获取实体的方法,而不会获得它的所有子/属性.
EDIT1:
道码:
@Repository
public interface FlightDao extends JpaRepository<Flight, Long> {
}
Run Code Online (Sandbox Code Playgroud)
EDIT2:
感谢Chlebik,我能够找出问题所在.像Chlebik所说,如果你试图访问由getOne()完整查询提取的实体的任何属性将被执行.在我的情况下,我在调试时检查行为,一次移动一行,我完全忘记了调试IDE时尝试访问对象属性以进行调试(或者至少是我认为正在发生的事情),所以调试触发器完整的查询执行.我停止调试,然后检查日志,一切似乎都正常.
getOne()vs findOne()(这个日志来自MySQL general_log而不是休眠.