2011-03-02 143 views
6

我试图实现一个简单的DAO。 我有一个道:Spring-Hibernate坚持不会导致插入

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

以及实体:

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

这里的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/>` 

除非我persist()merge()在不插入后调用flush()执行。 这是为什么? 如果我删除@Transactional,那么在刷新时出现“没有事务正在进行”的错误,但是如果删除刷新没有插入到DB中。

回答

10

是这样工作的,因为仅与@Transactional(readOnly = true)读你标记事务。

正如您所看到的,它不会使您的交易实际为只读,因为您仍然可以通过手动呼叫flush()来坚持更改。但是,它会在事务结束时禁用自动刷新功能,以便在没有手动刷新的情况下更改不会持久。

你需要无论是从类级别的注释去掉readOnly,或覆盖非只读方式与方法级别的注解:

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

还要注意的是事务划分通常适用于业务层的方法,而不是DAO方法。特别是,在编写DAO方法时,您实际上不知道哪些事务应该是只读的,哪些不是。此信息在设计业务层时可用,你可以在这个例子中看到:

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

我已经改变了'@ Transactional'为false,并且仍然没有插入。关于交易标界,我谨记在心,谢谢。 删除@ @ Transactional'也没有帮助。 – AlexV 2011-03-02 14:59:49

+0

@AlexV:看起来很奇怪。你怎么称呼这些方法? – axtavt 2011-03-02 15:39:57

+0

不确定你说我是怎么称呼这些方法的。我有一个单元测试,我称之为DAO'save()'方法。 – AlexV 2011-03-02 16:03:28

1

尝试事务传播设置所需,并删除所有flush(): -

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