0

我有一个 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

4 回答 4

1

r 是来自数据库的实体。当你修改它时,你要求 JPA 也修改数据库。

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

注意:当我说“在内存中”时,不要忘记它是一种事务性的内存。

于 2012-10-10T06:54:57.223 回答
1

我只是在方法之上添加了这个。

@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)

像魅力一样工作!

于 2012-10-10T07:12:14.460 回答
0

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

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

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

于 2012-10-10T07:10:03.917 回答
0

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

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

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

if(r.getOrg() == null) r.setOrg(orgFacade.find("011"));
r.setPassword(tempPwd.toString()); 
于 2012-10-10T07:26:11.163 回答