EntityManager.merge没有做任何事情

时间:2012-01-31 03:11:33

标签: java spring jpa eclipselink

我有一个用户实体:

@Entity
@Table( name = "bi_user" )
@SequenceGenerator( name = "USER_SEQ_GEN", sequenceName = "USER_SEQUENCE" )
public class User
        extends DataObjectAbstract<Long>
{
    private static final long serialVersionUID = -7870157016168718980L;

    /**
     * key for this instance. Should be managed by JPA provider.
     */
    @Id
    @GeneratedValue( strategy = GenerationType.SEQUENCE, generator = "USER_SEQ_GEN" )
    private Long key;

    /**
     * Username the user will use to login.  This should be an email address
     */
    @Column( nullable=false, unique=true)
    private String username;

    // etc. other columns and getters/setters
}

其中DataObjectAbstract是一个简单的@MappedSuperClass,它具有jpa版本和equals / hashcode定义。

我有一个基本dao类,看起来像这样

public abstract class BaseDaoAbstract<T extends DataObject<K>, K extends Serializable>
        implements BaseDao<T, K>
{

    @PersistenceContext
    private EntityManager em;

    /**
     * Save a new entity. If the entity has already been persisted, then merge
     * should be called instead.
     * 
     * @param entity The transient entity to be saved.
     * @return The persisted transient entity.
     */
    @Transactional
    public T persist( T entity )
    {
        em.persist( entity );
        return entity;
    }

    /**
     * merge the changes in this detached object into the current persistent
     * context and write through to the database. This should be called to save
     * entities that already exist in the database.
     * 
     * @param entity The entity to be merged
     * @return The merged entity.
     */
    @Transactional
    public T merge( T entity )
    {
        return em.merge( entity );
    }

    // other methods like persist, delete, refresh, findByKey that all delegate to em.
}

我在web.xml中定义了OpenEntityManagerInView过滤器,如下所示

<filter>
    <filter-name>openEntityManagerInViewFilter</filter-name>
    <filter-class>
        org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter
    </filter-class>
    <init-param>
        <param-name>entityManagerFactoryBeanName</param-name>
        <param-value>biEmf</param-value>
    </init-param>
</filter>

<filter-mapping>
    <filter-name>openEntityManagerInViewFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

我最近升级到eclipselink 2.3.2和Spring 3.1,并使用aspectJ for Spring从CGLIB代理转换为加载时编织,但我没有为eclipselink配置LTW。

问题出在这个代码中,它位于Spring ApplicationPistener中,请参阅注释。

        User user = userService.findByKey(userDetails.getKey());

        // THIS MERGE NEVER WRITES THROUGH TO THE DATABASE.
        // THIS DOESN'T WORK AS PERSIST EITHER
        user = userService.merge( user.loginSuccess() );

user.loginSuccess只设置一些字段并返回this我确定它正在通过代码,因为我得到了它周围的日志语句,我可以设置一个断点并遍历它。我的postgres日志没有显示任何流量进入合并的postgres。

我在没有问题的情况下保存其他所有内容,包括用户在更改密码时在其他位置,并且我知道此代码曾经工作过。这里有什么明显的错误吗?我是否错误地使用OpenEntityManagerInViewFilter?我是否需要使用@Transactional方法才能将实体视为托管?任何帮助表示赞赏。

更新 我按照prajeesh的建议尝试了冲洗。这是代码

@Transactional
public T merge( T entity )
{
    entity = em.merge( entity );
    em.flush();
    return entity;
}

com.bi.data的课程中。我在我的春季app配置文件中有这个

<context:component-scan base-package="com.bi.controller,com.bi.data,com.bi.web" />

在我的弹簧配置中,我有

<context:load-time-weaver/>
<tx:annotation-driven mode="aspectj"/>    

使用如下所示的aop.xml:

<aspectj>
    <weaver>
        <!-- only weave classes in our application-specific packages -->
        <include within="com.bi..*"/>
    </weaver>
</aspectj>

我得到了

javax.persistence.TransactionRequiredException: 
Exception Description: No transaction is currently active

所以事情显然是错误的配置,但是什么?

更新2: 我恢复了我的更改以启用加载时间编织,现在合并完成有或没有刷新,但我仍然不明白LTW的问题是什么......

5 个答案:

答案 0 :(得分:12)

em.flush()之后也尝试em.merge()。有时EntityManager会保留更改以便稍后更新。

答案 1 :(得分:4)

EntityManager autocommit为false。请使用以下交易;

EntityManager em = null;
EntityTransaction t = null;
try {
    em = emf.createEntityManager();
    t = em.getTransaction();
    t.begin();
    em.merge(myTestObject);
    t.commit();
} catch (Exception e) {
    t.rollback();
    throw new RuntimeException(e.getMessage());
}finally{
    if(em != null)
        em.close();
}

答案 2 :(得分:2)

我遇到了这个问题,并通过更改范围得到了解决。

@PersistenceContext(type=PersistenceContextType.EXTENDED)

参考:Manipulating Entities with EntityManager

答案 3 :(得分:1)

transaction.begin()transaction.end()方法在哪里?在RESOURCE_LOCAL中,您应该管理事务而不是应用程序...

答案 4 :(得分:0)

检查Spring配置文件中是否有以下行:   这样可以启用@Transactional注释支持,并确保mode =&#34; proxy&#34;, not mode =&#34; aspectj&#34; 已设置