Spring-Hibernate持久化不会导致插入 [英] Spring-Hibernate persist does not result in insert

查看:112
本文介绍了Spring-Hibernate持久化不会导致插入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图实现一个简单的DAO。
我有一个Dao:

  @Repository(iUserDao)
@Transactional(readOnly = true )
public class UserDao实现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();
返回true;
}

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

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

以及一个实体:

  @Entity 
@Table(name =users)
public class User {
private int id;
私人日期creationDate;

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

$ b $ 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;




$ b $ p $这些是appContext.xml:
` $ b $

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

< bean id =transactionManagerclass =org.springframework.orm.jpa.JpaTransactionManager
p:entityManagerFactory-ref =entityManagerFactory/>
class =org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter
p:database =MYSQLp:showSql =true/> ;

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

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

解决方案

它以这种方式工作,因为您将事务标记为只读 @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()可以参与有效的只读事务

$ b @Transactional
public void changeUserName(int id,String newName){
User u = dao.getById(ID); //或者不是
u.setName(newName); //更改将在交易结束时刷新


$ c $ <$ pre

I'm trying to implement a simple DAO. I have a Dao:

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

And an entity:

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

Here's 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/>`

Unless I call flush() after persist() or merge() the insert in not executed. Why is that? If I remove @Transactional then I get error on "no transaction is in progress" on flush, but if remove flush nothing inserted to the DB.

解决方案

It works this way because you marked transaction as read only with @Transactional(readOnly = true).

As you can see, it doesn't make your transactions actually read-only since you still can persist changes by calling flush() manually. However, it disables automatic flush at the end of transaction, so that changes are not persisted without manual flush.

You need either remove readOnly from class-level annotation, or override it on non-read-only methods with method-level annotations:

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

Also note that transaction demarcation is usually applied to service layer methods, not to DAO methods. In particular, when writing DAO methods you actually don't know which transactions should be read-only, and which are not. This information is available only when designing service layer, as you can see in this example:

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

这篇关于Spring-Hibernate持久化不会导致插入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆