2011-03-02 11 views
6

Sto provando a implementare un DAO semplice. Ho un Dao:Spring-Hibernate persist non risulta nell'inserimento

@Repository("iUserDao") 
@Transactional(readOnly = true) 
public class UserDao implements IUserDao { 
    private EntityManager entityManager; 

    @PersistenceContext 
    public void setEntityManager(EntityManager entityManager) { 
     this.entityManager = entityManager; 
    } 

    @Override 
    public User getById(int id) { 
     return entityManager.find(User.class, id); 
    } 

    @Override 
    public boolean save(User user) { 
     entityManager.persist(user); 
     entityManager.flush(); 
     return true; 
    } 

    @Override 
    public boolean update(User user) { 
     entityManager.merge(user); 
     entityManager.flush(); 
     return true; 
    } 

    @Override 
    public boolean delete(User user) { 
     user = entityManager.getReference(User.class, user.getId()); 
     if (user == null) 
      return false; 
     entityManager.remove(user); 
     entityManager.flush(); 
     return true; 
    } 

E un'entità:

@Entity 
@Table(name = "users") 
public class User { 
    private int id; 
    private Date creationDate; 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    public int getId() { 
     return id; 
    } 

    public User() { 
    } 

    public User(Date creationDate) { 
     this.creationDate = creationDate; 
    } 

    public void setId(int id) { 
     this.id = id; 
    } 

    public Date getCreationDate() { 
     return creationDate; 
    } 

    public void setCreationDate(Date creationDate) { 
     this.creationDate = creationDate; 
    } 
} 

Ecco appContext.xml: `

<bean id="entityManagerFactory" 
     class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" 
     p:dataSource-ref="dataSource" p:jpaVendorAdapter-ref="jpaAdapter" 
     p:persistenceUnitName="test"> 
    <property name="loadTimeWeaver"> 
     <bean 
       class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/> 
    </property> 
</bean> 

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" 
     p:entityManagerFactory-ref="entityManagerFactory"/> 
<bean id="jpaAdapter" 
     class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" 
     p:database="MYSQL" p:showSql="true"/> 

<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/> 
<tx:annotation-driven/>` 

A meno che io chiamo flush() dopo persist() o merge() l'inserto a non eseguito. Perché è quello? Se rimuovo @Transactional allora ottengo errore su "nessuna transazione è in corso" su flush, ma se rimuovere svuota nulla inserito nel DB.

risposta

10

Funziona in questo modo, perché hai segnato transazione come di sola lettura con @Transactional(readOnly = true).

Come si può vedere, non rende effettivamente le transazioni di sola lettura poiché è ancora possibile mantenere le modifiche chiamando lo flush() manualmente. Tuttavia, disabilita lo svuotamento automatico alla fine della transazione, in modo che le modifiche non vengano mantenute senza il flush manuale.

È necessario rimuovere readOnly da-livello di classe di annotazione, o ignorare che sulla non-lettura-solo metodi e le annotazioni a livello di metodo:

@Override 
@Transactional(readOnly = false) 
public boolean save(User user) { ... } 

Si noti inoltre che la demarcazione della transazione è di solito applicata ai metodi livello di servizio , non ai metodi DAO. In particolare, quando si scrivono metodi DAO in realtà non si sa quali transazioni devono essere di sola lettura e quali no. Questa informazione è disponibile solo durante la progettazione di livello di servizio, come si può vedere in questo esempio:

public class UserService { 
    @Autowired UserDAO dao; 

    @Transactional(readOnly = true) 
    public User getUserById(int id) { 
     return dao.getById(id); // getById() can participate in effectively read-only transaction 
    } 

    @Transactional 
    public void changeUserName(int id, String newName) { 
     User u = dao.getById(id); // Or not 
     u.setName(newName); // Change will be flushed at the end of transaction 
    } 
} 
+0

ho cambiato il '@ Transactional' false e ancora non c'è inserti. Per quanto riguarda la demarcazione delle transazioni, lo terrò a mente, grazie. Anche rimuovere '@ Transactional' non è stato d'aiuto. – AlexV

+0

@AlexV: sembra strano. Come chiamate questi metodi? – axtavt

+0

Non sai cosa intendi per come chiamo questi metodi. Ho un test unitario in cui chiamo il metodo DAO 'save()'. – AlexV

1

provare a impostare il propagazione transazionale a richiesta, e rimuovere tutti flush(): -

@Repository("iUserDao") 
@Transactional(propagation=Propagation.REQUIRED) 
public class UserDao implements IUserDao { 
    ... 
} 
Problemi correlati