2012-01-31 3 views
10

ho un'entità User:EntityManager.merge non facendo nulla

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

Dove DataObjectAbstract è un semplice @MappedSuperClass che ha una versione JPA e uguale/definizione codice hash.

ho una classe di base dao che assomiglia a questo

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

ho definito il filtro OpenEntityManagerInView in web.xml come segue

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

recente aggiorno a EclipseLink 2.3.2 e primavera 3.1 e convertiti da proxy CGLIB per caricare Time Weaving con aspectJ per Spring ma non ho configurato LTW per eclipselink.

Il problema è in questo codice che risiede in un ApplicationListener di primavera, vedere i commenti.

 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 solo stabilisce alcuni campi e restituisce this Sono certo che sta facendo con il codice perché ho affermazioni intorno ad esso il login e posso impostare un punto di interruzione e camminare attraverso di essa. Il mio registro postgres non mostra traffico che arriva a postgres per l'unione.

Sto salvando altre cose ovunque senza problemi, compresi gli utenti in un'altra posizione quando cambiano la password e so che questo codice funzionava. C'è qualcosa di evidentemente sbagliato? Sto usando OpenEntityManagerInViewFilter in modo errato? Dovrei aver bisogno di essere in un metodo @Transactional in modo che le entità possano essere considerate gestite? Qualsiasi aiuto è apprezzato.

Aggiornamento Ho provato il colore come suggerito da prajeesh. Ecco il codice

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

in una classe in com.bi.data. Ho questo nel mio primavera app config file di

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

Nella mia configurazione primavera ho

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

con un'aop.xml che assomiglia a questo:

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

e ho ottenuto un

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

Quindi qualcosa è ovviamente mal configurato, ma cosa?

Aggiornamento 2: sono ritornato mie modifiche per consentire il tempo di tessitura del carico e ora l'unione passa attraverso con o senza filo, ma io ancora non capisco quale sia il problema con LTW ...

+0

Sembra che la transazione sia configurata correttamente. Forse includi il tuo persistence.xml, assicurati di utilizzare RESOURCE_LOCAL. Abilita la registrazione migliore per vedere cosa sta succedendo. – James

+0

Grazie per le idee James. Lo darò un'occhiata dopo il lavoro. Sono abbastanza sicuro che stiamo usando RESOURCE_LOCAL perché siamo in esecuzione in Tomcat, quindi non l'ho mai fatto. – digitaljoel

+0

Hai provato ad aggiungere propagation = Propagation.REQUIRED all'annotazione @Transactional? –

risposta

12

Provare il em.flush() anche dopo il em.merge(). A volte il EntityManager mantiene solo le modifiche per l'aggiornamento più tardi.

+1

non ha funzionato per me – vicky

1

Dove sono i transaction.begin() e transaction.end() metodi? In RESOURCE_LOCAL si dovrebbe gestire la transazione e non l'applicazione ...

+0

Un'altra possibilità è la transazione è di sola lettura. – okwap

0

Controllare se è presente la seguente riga nel file di configurazione Primavera: Questo abilita il supporto di annotazione @Transactional, e anche fare in modo che la modalità =" proxy ", non mode =" aspectj " è impostato

+0

Il link non funziona più. –

2

L'autocommt di EntityManager è falso. Si prega di utilizzare la transazione come di seguito;

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

sto usando jpa e non consente em.getTransaction(), – vicky

+0

A volte JPA non riesce a trovare il file persistence.xml nel percorso. Dove il tuo percorso persistence.xml? Se il tuo em è nullo, sposta persistence.xml in src/main/java/META-INF/persistence.xml – ethemsulan