Improve performance javax.persistence transactions to remote database - mysql

When developing the application against my local database there were no problems with the speed of transactions, although the CPU usage was constantly at about 30 percents when performing several transactions per second, and when profiling most of the time was spent in javax methods handling the transactions with an average of 2.6 seconds per transaction. Therefore I'm using an ArrayList as a buffer and only sending the transaction when the size of the buffer exceeds 300 instances, which significantly lowered the CPU usage.
When I'm changing my persistence.xml to use a remote database instead (checked both RDS and a personal, off-site database) the minimum time for persisting/committing a batch of instances is about 20 seconds, which is too high since a transaction of 300 instances is required once every 5 seconds (on average).
I've tried to change the flushmode of the EntityManager to FlushModeType.COMMIT but it didn't change the performance noticeably. Increasing the size of the buffer before sending causes a stack overflow with the javax.persistence library for some (to me) unknown reason.
persistence.xml
<persistence-unit name="PU-data" transaction-type="RESOURCE_LOCAL">
<mapping-file>META-INF/orm.xml</mapping-file>
... // class, shared-cache-mode=none, validation-mode=none ...
<properties>
... // Authentication ...
<!-- Optimization attempts -->
<property name="eclipselink.jdbc.bind-parameters" value="true" />
<property name="eclipselink.jdbc.batch-writing" value="JDBC"/>
<property name="eclipselink.jdbc.batch-writing.size" value="300" />
<property name="eclipselink.jdbc.cache-statements" value="true" />
<property name="eclipselink.cache.shared.default" value="false" />
<property name="eclipselink.persistence-context.close-on-commit" value="true" />
<property name="eclipselink.persistence-context.flush-mode" value="commit" />
<property name="eclipselink.persistence-context.persist-on-commit" value="false" />
</properties>
</persistence-unit>
Facade handling the transactions
MouseFacade.bufferSemaphore.acquireUninterruptibly(1);
if (MouseFacade.buffer.size() >= 300) {
EntityManager entityManager = EMF.getEntityManager();
try {
entityManager.getTransaction().begin();
for (Mouse mouse : MouseFacade.buffer) {
entityManager.persist(mouse);
}
entityManager.getTransaction().commit();
} finally {
if (entityManager.getTransaction().isActive()) {
entityManager.getTransaction().rollback();
}
entityManager.close();
MouseFacade.buffer.clear();
}
}
MouseFacade.bufferSemaphore.release(1);
ORM mapping
<entity-mappings version="2.1" xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/orm" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<entity class="se.my.package.Mouse">
<table-generator name="ORD_SEQ" allocation-size="300"/>
</entity>
</entity-mappings>
Update
I've gone through the suggestions found at this page, called How to improve JPA performance by 1,825% (http://java-persistence-performance.blogspot.se/2011/06/how-to-improve-jpa-performance-by-1825.html), but there is no difference what so ever which makes me wonder whether I'm missing a key point about batch writing and MySQL. I've rewritten the entities not to rely on relationships and minimized my read-operations to 1 for the entire application in order to just focus on the write problems.
When looking through the EclipseLink log it doesn't look like batch-writing is being used at all, but instead 2 log entires are written for every instance which seems about right (300 instances * 2 connections * 24 latency = 14.4 seconds).
[EL Fine]: sql: 2013-03-31 01:35:29.249--ClientSession(1213059092)--Connection(662811604)--Thread(Thread[pool-1-thread-1,5,main])--SELECT LAST_INSERT_ID()
[EL Fine]: sql: 2013-03-31 01:35:29.274--ClientSession(1213059092)--Connection(662811604)--Thread(Thread[pool-1-thread-1,5,main])--INSERT INTO mouse (event, posX, posY, created, uid) VALUES (?, ?, ?, ?, ?)
bind => [12, 241, 250, 1364690113727, 1]
[EL Fine]: sql: 2013-03-31 01:35:29.298--ClientSession(1213059092)--Connection(662811604)--Thread(Thread[pool-1-thread-1,5,main])--SELECT LAST_INSERT_ID()
[EL Fine]: sql: 2013-03-31 01:35:29.323--ClientSession(1213059092)--Connection(662811604)--Thread(Thread[pool-1-thread-1,5,main])--INSERT INTO mouse (event, posX, posY, created, uid) VALUES (?, ?, ?, ?, ?)
bind => [12, 233, 296, 1364690113443, 1]
...
Progress
By changing to #GeneratedValue(strategy = GenerationType.TABLE) and allocationSize=300 I've managed to reduce the number of requests by 50%, although it looks as if bind are still sent on their own when checking the EclipseLink log, even though batch writing is supposedly enabled.
[EL Fine]: sql: 2013-03-31 01:35:29.323--ClientSession(1213059092)--Connection(662811604)--Thread(Thread[pool-1-thread-1,5,main])--INSERT INTO mouse (event, posX, posY, created, uid) VALUES (?, ?, ?, ?, ?)
bind => [..., ..., ..., ..., ...]
bind => [..., ..., ..., ..., ...]
bind => [..., ..., ..., ..., ...]
bind => [..., ..., ..., ..., ...]
bind => [..., ..., ..., ..., ...]
bind => [..., ..., ..., ..., ...]
bind => [..., ..., ..., ..., ...]
bind => [..., ..., ..., ..., ...]
bind => [..., ..., ..., ..., ...]
bind => [..., ..., ..., ..., ...]

Change your sequencing to use table sequencing allowing sequence numbers to be preallocated. What you have now forces each insert into its own statement so that the id can be found right after - which prevents batching. Table and other strategies allowing preallocation will give better performance if matched up with the size of your batches. Optimization #6 in http://java-persistence-performance.blogspot.se/2011/06/how-to-improve-jpa-performance-by-1825.html

Try enabling JDBC batch writing. I'm not sure what difference it would make, but it may be worth trying.

For batch writing in MySQL the MySQL JDBC driver does not batch statement unless you have set the following property in your conneciton URL,
?rewriteBatchedStatements=true
i.e.
jdbc:mysql://localhost:3306/db1?rewriteBatchedStatements=true

Related

How can I adjust query timeouts

I'm getting a timeout exception in my local dev environment for a Persistence SQL query.
Is the timeout configurable in Skyve?
There are 2 global timeouts in specified in the json config
eg
// Datastore definitions
"dataStores": {
// Skyve data store
"skyve": {
// JNDI name
"jndi": "java:/H2Demo",
// Dialect
"dialect": "org.skyve.impl.persistence.hibernate.dialect.H2SpatialDialect",
// Timeout for data store connections employed in general UI/forms processing - 0 indicates no timeout
"oltpConnectionTimeoutInSeconds": 30,
// Timeout for data store connections employed when running jobs and background tasks - 0 indicates no timeout
"asyncConnectionTimeoutInSeconds": 300
}
},
There are timeouts you can specify against each metadata query.
eg
<query name="qUsers" documentName="User" timeoutInSeconds="23">
All programmatic queries can set the timeout.
eg
Persistence p = CORE.getPersistence();
SQL sql = p.newSQL("select 1 ADM_Contact");
sql.setTimeoutInSeconds(200);
sql.scalarIterable(Number.class);
p.newSQL("select 1 ADM_Contact").noTimeout().scalarResults(Number.class);

How to force Hibernate to add ID column to insert query?

I'm using Spring Boot 1.4.0.RELEASE with the following DB connectors in dependencies
<!-- runtime dependencies -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
And there is an entity class with GenerationType.AUTO policy for ID generation (code below is not complete)
#Entity
#Table(name = "scanner_run")
public class ScannerRun extends BaseObject {
private Long id;
#Id #GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
public Long getId() {
return this.id;
}
}
There are not problems with insert of new entities, when H2 is used
spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
Hibernate generates insert into scanner_run (id, completed_ts, repository_id, started_ts, success) values (null, ?, ?, ?, ?) query and new record is created.
However with MySQL
spring.datasource.url=jdbc:mysql://localhost/db_dev?createDatabaseIfNotExist=true&useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&connectionCollation=utf8_general_ci
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
the generated query is insert into scanner_run (completed_ts, repository_id, started_ts, success) values (?, ?, ?, ?) - ID is not in the query - and it fails.
There are no other differences, only change in application.properties to swapp the database. The same code with older versions of Hibernate and MySQL connector works with the same installation of MySQL. MySQL connector resolves to mysql:mysql-connector-java:jar:5.1.39
Can you spot anything wrong?
The exact messages and exception in the logs are:
2016-08-26 14:38:03.964 DEBUG 32555 --- [ myScheduler-1] org.hibernate.SQL : insert into scanner_run (completed_ts, repository_id, started_ts, success) values (?, ?, ?, ?)
2016-08-26 14:38:03.967 WARN 32555 --- [ myScheduler-1] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 1364, SQLState: HY000
2016-08-26 14:38:03.967 ERROR 32555 --- [ myScheduler-1] o.h.engine.jdbc.spi.SqlExceptionHelper : Field 'id' doesn't have a default value
2016-08-26 14:38:03.979 ERROR 32555 --- [ myScheduler-1] o.s.s.s.TaskUtils$LoggingErrorHandler : Unexpected error occurred in scheduled task.
jvr.decrex.exception.ExecutionError: Failed to save ScannerRun{id=null, repository=/jv-ration/projects/jv-ration/deCrex/jvr-decrex/, startedTs=Fri Aug 26 14:38:03 CEST 2016, completedTs=null}
at jvr.decrex.service.impl.GenericManagerImpl.insert(GenericManagerImpl.java:107)
at jvr.decrex.scanner.service.impl.ScannerRunManagerImpl.createScan(ScannerRunManagerImpl.java:79)
.........
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.orm.jpa.JpaSystemException: could not execute statement; nested exception is org.hibernate.exception.GenericJDBCException: could not execute statement
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:333)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:244)
.........
at jvr.decrex.scanner.dao.jpa.ScannerRunDaoJpa$$EnhancerBySpringCGLIB$$5e6c846a.insert()
at jvr.decrex.service.impl.GenericManagerImpl.insert(GenericManagerImpl.java:105)
... 21 common frames omitted
Caused by: org.hibernate.exception.GenericJDBCException: could not execute statement
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:47)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:109)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:95)
..........
at com.sun.proxy.$Proxy126.persist(Unknown Source)
at jvr.decrex.dao.jpa.GenericDaoJpa.insert(GenericDaoJpa.java:137)
at jvr.decrex.dao.jpa.GenericDaoJpa$$FastClassBySpringCGLIB$$6605cd4e.invoke()
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:720)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
... 25 common frames omitted
Caused by: java.sql.SQLException: Field 'id' doesn't have a default value
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1078)
.........
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2376)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2360)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:204)
... 58 common frames omitted
I tried using older 5.1.27 version of mysql-connector-java, which works with older version of Hibernate - it throws the same error
You omit the database schema(s) so an amount of guesswork is to be made. The following is what can be said :-
AUTO generation strategy means the JPA provider can choose whatever it wants as the strategy. It seems that for MySQL it uses AUTOINCREMENT columns (equivalent to IDENTITY generation strategy), and for H2 it maybe uses a SEQUENCE (guessing since you provide no details of how). Maybe you don't have AUTOINCREMENT defined for the PK column with MySQL? but you can't use AUTO strategy in that case, and you are.
You could handle it by having an orm.xml for each datastore you will deploy to, and then you can use different generation strategies based on which datastore.
Alternatively choose TABLE generation strategy and it will insert the "id" column each time regardless of the datastore.
Or choose IDENTITY (when you use MySQL AUTOINCREMENT column for PK, and H2 IDENTITY column for PK) since H2 would then use that also (clearly this is not an option if you also need to support another datastore that has no such IDENTITY support).

Rollback in MyBatis using JDBC (no Spring, no containers)

I've seen all sorts of posts on using Spring and MyBatis with transactions, but I'm facing a problem with rollbacks not working with plain old JDBC.
My ( test / throwaway) code is pretty simple : I open a session, insert a rec, throw an error on purpose and rollback the transaction. However, it always commits.
public static void main (String[] args){
//-- omitted for brevity
try {
org.apache.ibatis.logging.LogFactory.useSlf4jLogging();
inputStream = Resources.getResourceAsStream("mybatis-config.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
sess = sqlSessionFactory.openSession(false);
BillsMapper mapper = sess.getMapper(BillsMapper.class);
BillState billState = new BillState();
billState.setBillId(-1);
billState.setLastName("TESTER");
billState.setFirstName("TESTER");
mapper.insert(billState);
logger.info("Post insert: key = {}", billState.getBillId());
if(1 == 1)
throw new RuntimeException("Error Thrown on purpose...testing rollback ");
sess.commit();
}catch(Exception e){
logger.error("Error: {}", e);
sess.rollback();
}finally{
sess.close();
logger.info("Finito!");
}
}
The logs show:
DEBUG | (BaseJdbcLogger.java:145) - ==> Preparing: insert into bills (users_userId, refId, firstName, ...
DEBUG | (BaseJdbcLogger.java:145) - ==> Parameters: 67(Integer), 67-120530180328(String), TESTER(String), ...
DEBUG | (BaseJdbcLogger.java:145) - <== Updates: 1
INFO | (TestAction.java:50) - Post insert: key = 2478
ERROR | (TestAction.java:56) - Error: {} java.lang.RuntimeException: Error Thrown on purpose...testing rollback at com.s2stest.TestAction.main(TestAction.java:53)
DEBUG | (JdbcTransaction.java:79) - Rolling back JDBC Connection [com.mysql.jdbc.JDBC4Connection#371e88fb]
DEBUG | (JdbcTransaction.java:122) - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection#371e88fb]
DEBUG | (JdbcTransaction.java:90) - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection#371e88fb]
DEBUG | (PooledDataSource.java:344) - Returned connection 924748027 to pool.
Note the resetting of autocommit before closing the connection.... Would resetting autcommit before closing the SqlSession cause my rolled-back transaction to be committed? If so, is this a bug? Has anyone gotten JDBC working with transactions? I need it for testing, and I'd value some help. Right now, no transactions can be rolled back.
I've looked at the MyBatis source, and it indeed calls resetAutocommit before closing the connection. I'm using MySQL 5.6 and mysql-connector-java-5.1.36.jar for the driver if someone has a workaround that they've found.
--- UPDATE ---
mybatis-config.xml is as follows:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<setting name="logImpl" value="SLF4J" />
</settings>
<typeAliases>
<package name="com.ship2storage.domain" />
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/mytestDb?zeroDateTimeBehavior=convertToNull" />
<property name="username" value="--shhh!!--" />
<property name="password" value="--shhh!!--" />
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/ship2storage/db/maps/BillsMapper.xml" />
</mappers>
</configuration>
OK, I've found the answer by digging deeper into my setup. It seems that the MySQL storage engine I installed for my test DB is ISAM. ISAM does not support transactions. I switched to InnoDB using the following SQL tidbit, and transactions now work with JDBC:
ALTER TABLE bills ENGINE=InnoDB;
I haven't tried this, but it looks like you can also do this temporarily too:
SET default_storage_engine=InnoDB;
Hopefully this will help someone. The code/config posted above works.

Unit testing and error 500

I'm an absolute newbie to Unit Testing, but I feel the need to learn something about it while I'm making my switch to CakePHP 3.
Following the manual, I've installed phpunit through composer (the same as I did for the whole cake package), created an empty test database and given config/app.php the right informations on how to connect.
Through the bake plugin I've baked some tests (I've got 19 tests now). Each one of them is (correctly) marked as incomplete.
Now, I'm trying to write a test for one of my controller's index function, this is what I've done:
public function testIndex()
{
$this->Session([
'Auth' => [
'User' => [
'id' => 1,
'email' => 'test#test.com',
'level' => 'adm',
]
]
]);
$this->get('/invoices');
$this->assertResponseOk();
}
The problem is that it just doesn't work, and I don't know what is throwing that 500 error...
Status code is not between 200 and 204
Failed asserting that 500 is equal to 204 or is less than 204.
What am I doing wrong?

idBag Generator Class Cast Exception

I've been trying to get an idbag working in hibernate. I been trying it against a MySql DB and a HSQLDB and I have also tried a couple different versions of Hibernate. Hibernate 4 and Hibernate 3 are giving slightly different information as to the cause of the error but both say the same thing in the main: Class Cast Exception.
I hosted all my code on bitbucket in a public repo and everything is there to include the DDL for creating a MySql or HSQL DB with the relevant tables. My HSQLDB version is 2.2.9 and the MySql version is 5.1.66 - My preference is to get it working on MySql.
Git Clone Command:
git clone https://pphi#bitbucket.org/pphi/idbag.git
Web Page:
https://pphi#bitbucket.org/pphi/idbag.git
When using Hibernate 4.0.1 I get this stack trace:
Hibernate: insert into idBagTest.Team (nickname, mascot) values (?, ?)
Hibernate: insert into idBagTest.Famous_Fan (first_name, last_name) values (?, ?)
Hibernate: insert into idBagTest.famous_fan_team (Team_id, team_fan_id, Famous_Fan_id ) values (?, ?, ?)
Exception in thread "main" java.lang.ClassCastException: org.hibernate.id.IdentifierGeneratorHelper$2 cannot be cast to java.lang.Long
at org.hibernate.type.descriptor.java.LongTypeDescriptor.unwrap(LongTypeDescriptor.java:36)
at org.hibernate.type.descriptor.sql.BigIntTypeDescriptor$1.doBind(BigIntTypeDescriptor.java:57)
at org.hibernate.type.descriptor.sql.BasicBinder.bind(BasicBinder.java:92)
at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:280)
at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:275)
at org.hibernate.persister.collection.AbstractCollectionPersister.writeIdentifier(AbstractCollectionPersister.java:919)
at org.hibernate.persister.collection.AbstractCollectionPersister.recreate(AbstractCollectionPersister.java:1252)
at org.hibernate.action.internal.CollectionRecreateAction.execute(CollectionRecreateAction.java:58)
at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:362)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:354)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:279)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:326)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:52)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1213)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:402)
at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:175)
at com.intertech.dao.TeamDaoHibernateImpl.saveTeam(TeamDaoHibernateImpl.java:19)
at com.intertech.Main.main(Main.java:22)
When using the Hibernate 3.1 I get this slightly different stack trace:
Hibernate: insert into Team (id, nickname, mascot) values (null, ?, ?)
Hibernate: insert into Famous_Fan (id, first_name, last_name) values (null, ?, ?)
Hibernate: insert into famous_fan_team (Team_id, team_fan_id, Famous_Fan_id ) values (?, ?, ?)
5120 [main] INFO org.hibernate.type.LongType - could not bind value 'POST_INSERT_INDICATOR' to parameter: 2; org.hibernate.id.IdentifierGeneratorFactory$2 cannot be cast to java.lang.Long
Exception in thread "main" java.lang.ClassCastException: org.hibernate.id.IdentifierGeneratorFactory$2 cannot be cast to java.lang.Long
at org.hibernate.type.LongType.set(LongType.java:65)
at org.hibernate.type.NullableType.nullSafeSet(NullableType.java:154)
at org.hibernate.type.NullableType.nullSafeSet(NullableType.java:136)
at org.hibernate.persister.collection.AbstractCollectionPersister.writeIdentifier(AbstractCollectionPersister.java:829)
at org.hibernate.persister.collection.AbstractCollectionPersister.recreate(AbstractCollectionPersister.java:1160)
at org.hibernate.action.CollectionRecreateAction.execute(CollectionRecreateAction.java:58)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:279)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:263)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:171)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1027)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:365)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:137)
at com.intertech.dao.TeamDaoHibernateImpl.saveTeam(TeamDaoHibernateImpl.java:19)
at com.intertech.Main.main(Main.java:22)
https://hibernate.onjira.com/browse/HHH-397
The use of identity for a generator class in the idBag is apparently not supported when using MySql and Hibernate. Replaced the generator class with increment and got this:
Hibernate: insert into idBagTest.Team (nickname, mascot) values (?, ?)
Hibernate: insert into idBagTest.Famous_Fan (first_name, last_name) values (?, ?)
Hibernate: select max(team_fan_id) from idBagTest.Famous_Fan_Team
Hibernate: insert into idBagTest.Famous_Fan_Team (Team_id, team_fan_id, Famous_Fan_id ) values (?, ?, ?)
The Repository has been updated with the working code.
I have came across the same error,
After some research I came to conclusion that it is depends on two things.
What DB you are using plus
What #GenericGenerator - what strategy you are using.
I was able to resolved issue with following configuration.
DB - MySQL
Changed strategy to increment from native
My code looks like:
#ElementCollection
#JoinTable(name="USERS_ADDRESSES", joinColumns=#JoinColumn(name="USER_ID"))
#GenericGenerator(name="hilogen",strategy="increment")
#CollectionId(columns={#Column(name="ADDR_ID")},generator="hilogen",type=#Type(type="long"))
private List addressList = new ArrayList();
Hope this help.
Thank,
Sagar Vyas