Duplicate Key when trying to Persist Data in a Service

I have a service running where I store some data in an Entity using DataManager. If I clear all the data in the table I am OK. But, with a table that already has data in it I am running into an error:

Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.6.2.cuba12): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry ‘704’ for key 'PRIMARY’
Error Code: 1062

It is telling me there is a duplicate key 704, which is correct, there is already a row with that primary key. The auto increment value is at 2374. If I insert a new record manually it grabs the next id properly (2375). My code does not for some reason, it started at 700 and is incrementing from there (701, 702, etc.). Why would manually inserting work OK but using the Datamanager it is starting at 700?

Using MySQL.
Table has an ID field, INT(11), that is the primary key and auto increment.

Code sample:


@Inject
private DataManager dataManager;

private void log()
{
    LogEntity logEntity = metadata.create(LogEntity.class);
    logEntity.setSomeValues("data");
    CommitContext commitContext = new CommitContext(logEntity);
    dataManager.commit(commitContext);
}

If you need more information I can provide it.

Hi Scott,

is it possible to create a minimal example project that shows the error, so that we can have a look at it? Cut everything out that is not necessary, e.g. the usage of mysql, in order to localize the problem more easy…

Bye
Mario

Interestingly, if I don’t use metadata.create it works.


// changed
LogEntity logEntity = metadata.create(LogEntity.class);

// to this and it works ok
LogEntity logEntity = new LogEntity();

What is the base class of LogEntity?

Metadata.create() automatically assigns IDs to BaseLongIdEntity/BaseIntegerIdEntity descendants, so they can clash with autoincrementing IDs assigned by the database.

LogEntity extends BaseIntegerIdEntity

So, does this mean we should not use Metadata.create() with BaseLongIdEntity/BaseIntegerIdEntity?

Ideally you should use BaseLongIdEntity/BaseIntegerIdEntity but with a plain long/integer column without autoincrement on the database level. Then Metadata.create() will assign IDs right after instantiating objects in memory which is the most convenient case for platform mechanisms and application code - you always have a unique ID even before saving the object.

If for some reason you need autoincrement in the database (e.g. you use the same tables in other applications), inherit your entities from BaseIdentityIdEntity. Then the ID type will be IdProxy and it will get a real value only after saving.

See also Base Entity Classes.