检索JPA实体会导致数据库中的更新

时间:2012-10-10 06:48:19

标签: persistence

我有一个EJB方法。

    public List<Rfsprsus> findAll() {
    List<Rfsprsus> rl = getEntityManager()
            .createNamedQuery("Rfsprsus.findAll", Rfsprsus.class)
            .getResultList();

    for(Rfsprsus r: rl) {
        StringBuilder tempPwd = new StringBuilder("");
        for(int i = 0; i < paramFacade.find().getPwlength(); i++) {
            tempPwd.append("a");
        }
        r.setPassword(tempPwd.toString());
        if(r.getOrg() == null) r.setOrg(orgFacade.find("011"));         }
    return rl;

但是,在调用此方法后,我检查数据库。我很惊讶 for循环实际上导致了更新

我不知道如何以及为什么,请解释一下!

4 个答案:

答案 0 :(得分:1)

r是从数据库中提交的实体。当您修改它时,您也要求JPA修改数据库。

哲学上,不要将JPA视为访问数据库的组件。请将其视为内存中存在的所有实体,JPA会在您需要时找到它们。如果您不使用这些实体,JPA将这些实体刷新到数据库这一事实主要是实现细节。

注意:当我说“在记忆中”时,不要忘记它是一种交易记忆。

答案 1 :(得分:1)

我刚刚在方法上添加了这个。

@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)

像魅力一样工作!

答案 2 :(得分:0)

我想说这是因为您正在处理活动事务中的附加实体。

也就是说,它们仍由实体经理管理。由实体管理器管理并且是正在进行的事务的一部分的实体就像数据库的实时链接。如果启动事务,从数据库中检索一些数据,然后通过使用setter更改对象数据,然后关闭它将更新数据库的事务。在这些情况下,您不需要persist或merge命令。

如果要操作从数据库返回的数据但不更新数据库,请分离实体或使用DTO(数据传输对象)。也就是说,更改事务范围之外的数据,或者将数据传输到不由实体管理器管理的对象中。

答案 3 :(得分:0)

更新可能发生在以下几行之间:

r.setPassword(tempPwd.toString()); 
if(r.getOrg() == null) r.setOrg(orgFacade.find("011"));

首先,您要更新内存中的实体r。我不确定orgFacade.find()是做什么的,但我想它会查询数据库。在执行查询之前,JPA会刷新对DB的挂起更改,以防查询“触及”已更新的对象r(请注意,所有内容都在一个事务中执行)。所以我猜密码在DB中更新为orgFacade.find()的副作用。 解决方案可能很简单,只需更改上述行的顺序:

if(r.getOrg() == null) r.setOrg(orgFacade.find("011"));
r.setPassword(tempPwd.toString());