views:

416

answers:

3

I'm try to insert or update db record with following code:

Category category = new Category(); 
category.setName('catName');
category.setId(1L);
categoryDao.saveOrUpdate(category);

When there is a category with id=1 already in database everything works. But if there is no record with id=1 I got following exception:

org.hibernate.StaleStateException:
Batch update returned unexpected row count from update [0]; actual row count: 0; 
expected: 1:

Here is my Category class setters, getters and constructors ommited for clarity:

    @Entity
    public class Category {

        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        private Long id;

        private String name;

        @ManyToOne
        private Category parent;

        @OneToMany(fetch = FetchType.LAZY, mappedBy = "parent")
        private List<Category> categories = new ArrayList<Category>();
}

In the console I see this hibernate query:

update
    Category
set
    name=?,
    parent_id=?
where
    id=?

So looks like hibernates tryis to update record instead of inserting new. What am I doing wrong here?

+2  A: 

This is by design.

Hibernate only decides based on the id if it should perform an update or an insert. If it would consider what's already there in the database, it would have to perform an additional query, but it doesn't do this.

Ids are normally managed by Hibernate, unless you map it as generator="assigned" (don't know how this looks using annotations). So you shouldn't just assign a value to it.

In this case, the Id is even given by the database. So if your application would generate Ids at the same time, it would result in duplicated Ids. (And most database do not allow inserting values to auto columns, so it would technically be impossible to store your id).

If you want to generate your own Ids, use generator="assigned", and store it using merge. This will do what you expect: it searches the record in the database, when it exists it will update it, when not it will insert it.

Stefan Steinegger
I just thought if I manually set the id hibernate will be able to recognize if record already in db and will perform update and if not it will perform save. So in my case you suggest to check existence of the object manually and then choose save it or update?
Vladimir
You could do this. But - you should never write to an Id that is managed by the database or hibernate. So this situation should not occur. You must make a choice for who should generate the id.
Stefan Steinegger
A: 

try to use save method alone if the rowcount of the table is 0 else use saveorupdate method.

TbmBizz
...and when there is another record?
Stefan Steinegger
A: 

when i use saveOrUpdate(Object) method of Hibernate. How can I know that row is updated or Added into table???

Vikram