HibernateTemplate save执行插入但不执行更新

时间:2013-02-26 14:30:29

标签: spring hibernate transactions

我有一个典型的Spring / Hibernate设置。这是我的春季配置:

<context:annotation-config />

<context:component-scan base-package="com.myco.myapp.modules" />

<tx:annotation-driven transaction-manager="transactionManager"/>

<bean id="sessionFactory"
...     
</bean>

<bean id="transactionManager"
    class="org.springframework.orm.hibernate3.HibernateTransactionManager">
  <property name="sessionFactory" ref="sessionFactory" />
</bean>

我有一个BaseRepository:

@Transactional(propagation = Propagation.MANDATORY)
public final T save(final T entity) throws RepositoryException {
    try {
        getHibernateTemplate().save(entity);
        return entity;
    } catch (DataAccessException e) {
        throw new EntityCouldNotBeSavedException(getPersistentClass(),
            e);
    }
}

扩展它的Repository类:

@Repository
public class PersonRepositoryImpl extends BaseRepositoryImpl<Person, String>

和服务:

@Service
public class PersonServiceImpl {
  @Autowired
  private PersonRepository _personRespository;

我调用以下方法saveSomeStuff(),当我使用BaseRepository.save()插入时,它完美地工作。但是当我尝试更新时,它并没有做出改变:

@Override
@Transactional
public void saveSomeStuff() {

    try {

        Person existingPerson = _personRespository.findById("1");

        existingPerson.setName("John");

        _personRespository.save(existingPerson);

        Person dbExistingPerson = _personRespository.findById("1");

        // This prints "John".
        System.out.println(dbExistingPerson.getName());

        Person newPerson = new Person();
        newPerson.setName("Jack");
        _personRespository.save(newPerson);

    } catch (RepositoryException e) {
        e1.printStackTrace();

    }
}

我以为我可能会遇到transaccionality问题,但正如我所说,在离开Service方法后,新Person将保留在数据库中。在日志中我看到:

插入人...

但是,我所做的更新没有保留,并且没有错误,也没有更新&#39;日志中的sql语句。我认为HibernateTemplate.save()方法可能是问题,但是在saveSomeStuff()方法中,从数据库加载Person后,我执行System.out,并且从数据库加载的Person具有更新的名称。 / p>

我在这里缺少什么?

4 个答案:

答案 0 :(得分:1)

有一个单独的方法saveOrUpdate(entity)。如果您不希望hibernate在保存时生成id,则可以使用它。

答案 1 :(得分:0)

保存方法将保留实体。如果不存在标识符,将分配标识符。如果有的话,它实质上是在进行更新。返回生成的实体ID。

答案 2 :(得分:0)

找出问题所在。如果我已经包含了我的实体课程,那么有人可能会比我更快地看到它。

@Entity
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
@Immutable
@Table(name = "PEOPLE")
public class Person {
  ...
}

最初我收到了缓存错误:

java.lang.UnsupportedOperationException: Can't write to a readonly object

快速解决方案?添加@Immutable注释。但是如果你阅读了它的文档:

An immutable entity may not be updated by the application. 
Updates to an immutable entity will be ignored, but no exception is thrown.

这解释了为什么1)更新被忽略,2)没有异常被抛出。

所以我摆脱了@Immutable注释并将Cache更改为:

 @Cache(usage = CacheConcurrencyStrategy.READ_WRITE)

现在一切正常。

总结:rtfm。

答案 3 :(得分:0)

我偶然发现了同样的问题。该实体已插入到数据库中,但在更新某些未更新的列时,日志中没有错误。在浏览了实体类之后,我发现我已经注释了我的一些字段,如下所示

@Column(name = "CREATED_DT", updatable = false)
private Date createdOn;

从注释中删除可更新属性后,更新工作正常。