【问题标题】:Persistence Context with RooRoo 的持久性上下文
【发布时间】:2013-05-22 16:21:45
【问题描述】:

对于事物何时分离以及持久性上下文的范围,我有点困惑。我的实体是否仅在 roo 生成的每个方法中“管理”?我之所以问,是因为我已经读过在分离的实例上调用 refresh() 应该会引发异常,但是然后我在没有先合并实体的情况下调用 refresh() 我似乎没有收到错误...

有人可以根据实体管理器的生命周期以及何时在单个合并、持久化、删除方法中管理和分离对象来解释 Roo 代码...

// WARNING: DO NOT EDIT THIS FILE. THIS FILE IS MANAGED BY SPRING ROO.
// You may push code into the target .java compilation unit if you wish to edit any member(s).


import java.math.BigDecimal;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.transaction.annotation.Transactional;

privileged aspect AdminDirectRole_Roo_Jpa_ActiveRecord {

    @PersistenceContext
    transient EntityManager AdminDirectRole.entityManager;

    public static final EntityManager AdminDirectRole.entityManager() {
        EntityManager em = new AdminDirectRole().entityManager;
        if (em == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
        return em;
    }

    public static long AdminDirectRole.countAdminDirectRoles() {
        return entityManager().createQuery("SELECT COUNT(o) FROM AdminDirectRole o", Long.class).getSingleResult();
    }

    public static List<AdminDirectRole> AdminDirectRole.findAllAdminDirectRoles() {
        return entityManager().createQuery("SELECT o FROM AdminDirectRole o", AdminDirectRole.class).getResultList();
    }

    public static AdminDirectRole AdminDirectRole.findAdminDirectRole(BigDecimal id) {
        if (id == null) return null;
        return entityManager().find(AdminDirectRole.class, id);
    }

    public static List<AdminDirectRole> AdminDirectRole.findAdminDirectRoleEntries(int firstResult, int maxResults) {
        return entityManager().createQuery("SELECT o FROM AdminDirectRole o", AdminDirectRole.class).setFirstResult(firstResult).setMaxResults(maxResults).getResultList();
    }

    @Transactional
    public void AdminDirectRole.persist() {
        if (this.entityManager == null) this.entityManager = entityManager();
        this.entityManager.persist(this);
    }

    @Transactional
    public void AdminDirectRole.remove() {
        if (this.entityManager == null) this.entityManager = entityManager();
        if (this.entityManager.contains(this)) {
            this.entityManager.remove(this);
        } else {
            AdminDirectRole attached = AdminDirectRole.findAdminDirectRole(this.id);
            this.entityManager.remove(attached);
        }
    }

    @Transactional
    public void AdminDirectRole.flush() {
        if (this.entityManager == null) this.entityManager = entityManager();
        this.entityManager.flush();
    }

    @Transactional
    public void AdminDirectRole.clear() {
        if (this.entityManager == null) this.entityManager = entityManager();
        this.entityManager.clear();
    }

    @Transactional
    public AdminDirectRole AdminDirectRole.merge() {
        if (this.entityManager == null) this.entityManager = entityManager();
        AdminDirectRole merged = this.entityManager.merge(this);
        this.entityManager.flush();
        return merged;
    }

}

任何建议表示赞赏。我创建了这个方法,期望它由于我没有将实体合并到任何持久性上下文中而失败,并且没有引发异常?

@Transactional
    public void refresh() {
        if (this.entityManager == null) this.entityManager = entityManager();
        entityManager.refresh(this);
    }

【问题讨论】:

  • 你怎么知道对象是分离的?
  • 实际上现在开始看到异常原因:java.lang.IllegalArgumentException:无法刷新非托管对象:AdminDirectRole[id=2,roleCode=ADMS_USER,roleName=ADMS User]。
  • 我应该这样做:@Transactional public AdminDirectRole refresh() { if (this.entityManager == null) this.entityManager = entityManager(); AdminDirectRole 刷新 = this.entityManager.merge(this); entityManager.refresh(刷新);返回刷新; }

标签: java jpa spring-roo


【解决方案1】:

持久化上下文默认绑定到事务。我假设任何代码检索 AdminDirectRole 的实例并调用刷新方法都用@Transactional 包装?换句话说:

//Will not throw an exception
@Transactional
public void foo(AdminDirectRole detached) {
  detached.merge();
  detached.refresh();
}

//Will throw an exception unless whatever is calling bar() has an @Transactional annotation (or whatever is calling whatever is calling bar and so on)
public void bar(AdminDirectRole detached) {
  detached.merge();
  detached.refresh();
}

【讨论】:

  • 嗨,第一个是抛出异常。在以第一种方法刷新之前,我必须将其合并到上下文中,否则会出现非托管异常。我正在使用@Transactional。
  • ....添加我没有在您可能已经管理的事务中使用 Find 进行查找。我必须合并以避免刷新时出现异常。不知道为什么要在刷新之前找到...如果您重新查找,刷新没有意义吗?
  • 这只是一个简单的例子,我会更新更真实的。需要明确的是,您没有任何理由必须进行刷新。如果您没有使用默认刷新模式(例如,仅在提交或手动时),那么您可能需要刷新。如果您使用的是本机语句,则可能需要刷新。最后,如果您的数据库使用的是 READ_COMMITTED 或更低的隔离级别,您可能需要刷新,尽管我会质疑依赖这种刷新的设计。
  • 嗨,在 JSF 中,我们有会话范围 bean,并且在会话开始时创建了一些实体,并且在执行 JPA CRUD 操作时,我们正在从内存中的集合中添加和删除实体,然后合并更改。但是如果其他用户正在对这些实体进行更改,那么我们需要定期刷新我会想到的,否则我们基于会话的实体将不能代表数据库。至少我是这么认为的。
  • 您是说您的 JPA EntityManager 持续多个 Web 请求和事务吗?如果是这样,那么您可能希望在每个请求开始时刷新一些内容是有道理的。如果不是,那么您无法保证您正在使用最新的对象。有人总是可以在您刷新和实际读取属性之间更新对象。如果您必须保证,那么您将不得不使用悲观锁定,但通常应用程序可以在没有该保证的情况下逃脱。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-24
  • 1970-01-01
  • 2014-05-07
  • 2023-03-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多