Reputation: 487
I have a typical Spring / Hibernate setup. Here's my spring config:
<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>
I have a 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);
}
}
And a Repository class that extends it:
@Repository
public class PersonRepositoryImpl extends BaseRepositoryImpl<Person, String>
And a Service:
@Service
public class PersonServiceImpl {
@Autowired
private PersonRepository _personRespository;
I call the following method, saveSomeStuff(), an when I insert using BaseRepository.save() it works perfectly. But when I try to update, it doesn't make the change:
@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();
}
}
I thought I might have a transaccionality problem, but as I said, upon leaving the Service method the new Person is persisted in the database. In the log I see:
insert into person ...
However, the update I made is not persisted, and there is no error and no 'update' sql statement in the log. I thought the HibernateTemplate.save() method might be the problem but from within the saveSomeStuff() method, after loading the Person from the database, I do a System.out, and the Person loaded from the database has the updated name.
What am I missing here?
Upvotes: 0
Views: 7017
Reputation: 139
I had stumbled upon the same problem. The entity was getting inserted into the database, but while updating some of the columns where not getting updated and there were no errors in the log. After going through the entity class, I figured out that I had annotated some of my fields as below
@Column(name = "CREATED_DT", updatable = false)
private Date createdOn;
After removing the updatable attribute from the annotation, the update was working fine.
Upvotes: 0
Reputation: 487
Figured out the problem. If I had included my Entity class, someone probably would have seen it sooner than me.
@Entity
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
@Immutable
@Table(name = "PEOPLE")
public class Person {
...
}
Initially I was getting a cache error:
java.lang.UnsupportedOperationException: Can't write to a readonly object
The quick solution? Add the @Immutable annotation. But if you read the docs for it:
An immutable entity may not be updated by the application.
Updates to an immutable entity will be ignored, but no exception is thrown.
Which explains why 1) updates were being ignored and 2) no exceptions were being thrown.
So I got rid of the @Immutable annotation and changed Cache to:
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
And now everything works fine.
In summary: rtfm.
Upvotes: 0
Reputation: 1
Save method will Persists an entity. Will assign an identifier if one doesn't exist. If one does, it's essentially doing an update. Returns the generated ID of the entity.
Upvotes: 0
Reputation: 12880
There is a separate method, saveOrUpdate(entity)
. You can use it if you don't want hibernate to generate id while saving.
Upvotes: 1