2012-01-31 12 views
10

que tienen una entidad Usuario:EntityManager.merge no hacer nada

@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 
} 

Dónde DataObjectAbstract es un simple @MappedSuperClass que tiene una versión de la APP y es igual a/definición código hash.

tengo una clase DAO base que se parece a esto

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. 
} 

he definido el filtro OpenEntityManagerInView en web.xml de la siguiente manera

<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> 

recientemente migrar a EclipseLink 2.3.2 y primavera 3.1 y convertido desde proxies CGLIB a Load Time Weaving con aspectJ para Spring pero no configuré LTW para eclipselink.

El problema está en este código que vive en Spring ApplicationListener, ver comentarios.

 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 simplemente establece algunos campos y devuelve this Estoy seguro de que se está haciendo a través del código porque consigo declaraciones alrededor conectarse y puedo establecer un punto de interrupción y caminar a través de él. Mi registro de postgres no muestra ningún tráfico que llegue a postgres para la fusión.

Estoy guardando otras cosas sin problema, incluidos los usuarios en otra ubicación cuando cambian su contraseña, y sé que este código solía funcionar. ¿Hay algo obviamente malo aquí? ¿Estoy usando el OpenEntityManagerInViewFilter incorrectamente? ¿Debería estar en un método @Transactional para que las entidades se consideren administradas? Cualquier ayuda es apreciada.

Actualización Probé la descarga según lo sugerido por prajeesh. Aquí está el código

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

en una clase en com.bi.data. Tengo esto en mi primavera aplicación de configuración presentar

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

En mi configuración del resorte tengo

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

con un aop.xml que tiene este aspecto:

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

y me dieron una

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

Así que algo es obviamente mal configurado, ¿pero qué?

Actualización 2: me volvieron mis cambios para permitir la carga del tiempo de tejer y ahora la fusión sigue adelante con o sin el rubor, pero yo todavía no entiendo cuál es el problema con LTW ...

+0

Parece que tiene la transacción configurada correctamente. Quizás incluya su persistence.xml, asegúrese de estar utilizando RESOURCE_LOCAL. Habilite el inicio de sesión en el mejor para ver qué está sucediendo. – James

+0

Gracias por las ideas James. Lo echaré un vistazo después del trabajo. Estoy bastante seguro de que estamos utilizando RESOURCE_LOCAL porque estamos ejecutando en tomcat, nunca JTA. – digitaljoel

+0

¿Ha intentado agregar propagation = Propagation.REQUIRED a la anotación @Transactional? –

Respuesta

12

Pruebe el em.flush() también después del em.merge(). Algunas veces, el EntityManager solo conserva los cambios para actualizarse más tarde.

+1

no funcionó para mí – vicky

1

¿Dónde está los métodos transaction.begin() y transaction.end()? En RESOURCE_LOCAL que debe gestionar la transacción y no la aplicación ...

+0

Otra posibilidad es que la transacción sea de solo lectura. – okwap

0

Comprobar si existe la siguiente línea en el fichero de configuración de primavera: Esto activa el soporte de anotación @Transactional, y también asegurarse de que el modo =" proxy ", not mode =" aspectj " se establece

+0

El enlace ya no funciona. –

2

EntityManager autocommit es falso. Utilice la transacción como a continuación;

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(); 
} 
+0

estoy usando jpa y no permite em.getTransaction(), – vicky

+0

A veces, JPA no puede encontrar el archivo persistence.xml en la ruta. ¿Dónde está tu ruta persistence.xml? Si su em es nulo, mueva persistence.xml a src/main/java/META-INF/persistence.xml – ethemsulan