Question

I am new with Spring, my application, developed with Spring Roo has a Cron that every day download some files and update a database.

The update is done, after downloading and parsing the files, using merge(), an Entity class Dataset has a list called resources, after the download I do:

dataset.setResources(resources);
dataset.merge();

and dataset.merge() does the following:

@Transactional
public Dataset Dataset.merge() {
    if (this.entityManager == null) this.entityManager = entityManager();
    Dataset merged = this.entityManager.merge(this);
    this.entityManager.flush();
    return merged;
}

I expect that doing dataset.setResources(resources); I would overwrite the filed resources, and so even the database entry would be overwritten.

But I get double entries in the database: every resource appear twice, with different IDs (incremental).

How can I succed in let my application doing updates and not insert? A naive solution would be delete manually the old resource and then call merge(); is this the way or is there some more smart solution?

Was it helpful?

Solution

This situation occurs when you use Hibernate as persistence engine and your entities have version field.

Normally the ID field is what we need for merging a detached object with its persistent state in the database, but Hibernate takes the version field in account and if you don't set it (it is null) Hibernate discards the value of ID field and creates a new object with new ID.

To know if you are affected by this strange feature of Hibernate, set a value in the version field, if an Exception is thrown you got it. In that case the best way to solve it is the data to parse contain the right value of version. Another ways are to disable version checking (see Hibernate ref guide to know about it) or load persistent state before merging.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top