I have a table
CREATE TABLE `SomeEntity` ( `id` int(11) NOT NULL AUTO_INCREMENT, `subid` int(11) NOT NULL DEFAULT '0', PRIMARY KEY (`id`,`subid`),
I have an entity class with an auto-increment field in it. I want to read the auto increment identifier assigned to it when it is saved
Getter annotations are given below.
private long id; private int subid; @Id @GeneratedValue **//How do i correct this to have multiple rows with same id and different subid** @Column(name = "id") public long getId() { return id; } @Id @Column(name = "subid") public int getSubid() { return subid; }
I want to have objects like
id 1 subid 0 id 1 subid 1 id 1 subid 2 id 2 subid 0
The default subid is 0 in the database, and I am gradually increasing it for updates on this line. I tried a solution, as in this SO JPA post - returning an automatically generated identifier after saving ()
@Transactional @Override public void daoSaveEntity(SomeEntity entity) { entityManager.persist(entity); }
Now, outside of this transaction, I'm trying to get the auto increment id
@Override public long serviceSaveEntity(SomeEntity entity) { dao.daoSaveEntity(entity); return entity.getId(); }
I am calling this from a web service
@POST @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) public Response createEntity(SomeEntity entity) {
The update method is given below.
@Transactional public void updateReportJob(SomeEntity someEntity) { Query query = entityManager .createQuery("UPDATE SomeEntity SET state=:newState WHERE id = :id"); query.setParameter("newState","PASSIVE"); query.setParameter("id", id); query.executeUpdate(); double rand = Math.random(); int i = (int) (rand * 300); try { Thread.sleep(i);
I am sending N simultaneous updates from N threads for an object with Id 1 and several other properties as shown below
SomeEnity entity = new SomeEntity ();
entity.setId(1); long num = Thread.currentThread().getId(); entity.setFieldOne("FieldOne" + num); entity.setFieldTwo("" + i); entity.setFieldThree("" + j); i++; j++;
Case 1 using @Id in id and @Id annotations for subid and `entityManager.persist 'in update When I worked with 300 threads, some with connection error' too many connections' Database status
id 1 subid 0 id 1 subid 1 id 1 subid 2 .. .... id 1 subid 150
the subad is always incremental, the race condition is only what will be ACTIVE, undefined due to the race condition
Case 2 with @Id in id and @Id annotations in subid and `entityManager.merge 'in update
id 1 subad 0 id 1 subid 0 id 2 subid 0 ...... id 151 subid 0 (Perhaps it is only a coincidence that another thread than case 1 was successful?)
Case 3 With @GeneratedValue and @Id in id and ** NO @Id annotation by subid and entityManager.persist in update ** exception - A separate object passed for saving
Case 3 With @GeneratedValue and @Id in id and ** NO @Id annotation by subid and entityManager.merge in the update ** if the update is performed sequentially, the state of the database
id 1 subid 0
after next update
id 1 subid 1
after updating each new version of the update (which results in only one line at a time)
id 1 subid 2
Case 4, similar to case 3 with parallel updates if run simultaneously (with 300 threads), I get the following exception
org.hibernate.HibernateException: More than one row with the given identifier was found: 1
Database status
id 1 subid 2 (Only one thread would be successful, but due to an updated rank status from 0 to 2)
Case 5 From @GeneratedValue and @Id to id and @Id annotations to subad
Create also fails with subid org.hibernate.PropertyAccessException: IllegalArgumentException occurred while calling setter of SomeEntity.id
Please explain the reasons. From javadoc methods, I know that
persist - make the instance manageable and persistent.
merge - merge the state of this object into the current save context.
My question is more about how hibernate manages annotations. Why, in case 3, is there a single object exception if the session is not already closed? Why is there a IllegalArgumentException in case 5?
I am using hibernate 3.6 mysql 5 and Spring 4 Also try specifying such incremental id and subad. (Using a custom SelectGenerator with a demo implementation or in any other way without executing the concat column)