I am trying to optimize a JPA implementation using EclipseLink. I added batch operations to it. But it still takes a long time to make 50,000 inserts. It takes more than 10 times the time it takes to perform the same insert using raw SQL with JDBC.
To make sure that batch operations actually work, I used Wireshark to check my packages and did not use batch inserts.
Here is one of the insert packages:

It does not:
INSERT INTO ENTITYCLASSTEST (LASTNAME, NAME) VALUES ('sfirosijfhgdoi 0', 'dsufius0'), ('sfirosijfhgdoi 0', 'dsufius0'), ('sfirosijfhgdoi 0', 'dsufius0'), ('sfirosijfhgdoi 0', 'dsufius0')... and so on
I expected it to do the same as above, but it inserts one line into a package, not multiple lines per package.
Here is my Entity class:
@Entity public class EntityClassTest implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; private String lastname; public EntityClassTest() { } public EntityClassTest(Long id, String name, String lastname) { this.id = id; this.name = name; this.lastname = lastname; } public EntityClassTest(String name, String lastname) { this.name = name; this.lastname = lastname; } public Long getId() { return id; } public String getName() { return name; } public String getLastName() { return lastname; } public void setId(Long id) { this.id = id; } public void setName(String name) { this.name = name; } public void setLastName(String lastname) { this.lastname = lastname; } @Override public int hashCode() { int hash = 0; hash += (id != null ? id.hashCode() : 0); return hash; } @Override public boolean equals(Object object) {
And here is my persist method, which gets a List and stores all the objects inside.
public void insertListToTable(final String persistenceUnit, final List list) throws SQLException { final EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory(persistenceUnit); final EntityManager entityManager = entityManagerFactory.createEntityManager(); final EntityTransaction transaction = entityManager.getTransaction(); try { final int listSize = list.size(); transaction.begin(); for (int i = 0; i<listSize; i++) {
And my persistence.xml , where I set 500 as the batch value, file:
<?xml version="1.0" encoding="UTF-8"?> <persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"> <persistence-unit name="ExternalServer" transaction-type="RESOURCE_LOCAL"> <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> <class>model.EntityClassTest</class> <properties> <property name="javax.persistence.jdbc.url" value="jdbc:mysql://myServer:3306/testdb?zeroDateTimeBehavior=convertToNull"/> <property name="javax.persistence.jdbc.user" value="testdbuser"/> <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/> <property name="javax.persistence.jdbc.password" value="myPassword"/> <property name="javax.persistence.schema-generation.database.action" value="create"/> <property name="eclipselink.weaving" value="static"/> <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/> <property name="eclipselink.target-database" value="MySQL"/> <property name="javax.persistence.schema-generation.database.action" value="create"/> <property name="eclipselink.logging.level" value="OFF"/> <property name="eclipselink.jdbc.batch-writing" value="JDBC"/> <property name="eclipselink.jdbc.batch-writing.size" value="500"/> </properties> </persistence-unit> </persistence>
So my question is: why is this not a batch insert? I believe that EclipseLink is configured to do this from what I read on the EclipseLink website, and here too.
//////////////////////////// EDIT /////////////////// /////
As suggested by Chris, I changed this @GeneratedValue(strategy = GenerationType.IDENTITY) to @GeneratedValue(strategy = GenerationType.SEQUENCE) in my EntityClassTest and re-run the test and the packets are sent as before (for example, the image I posted above ) Therefore, I did not fix my problem, I'm afraid.
//////////////////////////// EDIT 2 //////////////////// ////
I changed the logging level in persistence.xml to FINEST , as shown below.
<property name="eclipselink.logging.level" value="FINEST"/>
And so the magazine is created. I put it in pastebin because it is quite long.
http://pastebin.com/rKihCKMW
You seem to be calling Execute query InsertObjectQuery quite a few times.
////////////////////////// EDIT 3 ////////////////// ////
Here is the version for each component that I use.
+-------------------------+------------------------------+ | Variable_name | Value | +-------------------------+------------------------------+ | innodb_version | 5.6.12 | | protocol_version | 10 | | slave_type_conversions | | | version | 5.6.12-log | | version_comment | MySQL Community Server (GPL) | | version_compile_machine | x86_64 | | version_compile_os | Win64 | +-------------------------+------------------------------+ Netbeans 8.0 EclipseLink (JPA 2.1) mysql-connector-java-5.1.24.jar
////////////////////////// EDIT 4 //////////////////// ////
After CuriousMind's answer, I edited the EntityClassTest id EntityClassTest for:
@Id @GeneratedValue(strategy = GenerationType.AUTO, generator="id-seq-gen") @SequenceGenerator( name="id-seq-gen", sequenceName="ID_SEQ_GEN", allocationSize=500 ) private Long id;
But this did not solve my problem, I still get one single insert for each package (as described above) and in the EclipseLink log, which I get:
[EL Fine]: sql: 2014-10-19 06:44:02.608--ClientSession(824177287)--Connection(1674390738)--Thread(Thread[main,5,main])--SELECT LAST_INSERT_ID() [EL Finest]: sequencing: 2014-10-19 06:44:02.608--UnitOfWork(1985011414)--Thread(Thread[main,5,main])--assign sequence to the object (1.251 -> database.EntityClassTest [id=null ]) [EL Finest]: query: 2014-10-19 06:44:02.608--UnitOfWork(1985011414)--Thread(Thread[main,5,main])--Execute query InsertObjectQuery(database.EntityClassTest [id=null ]) [EL Finest]: query: 2014-10-19 06:44:02.608--ClientSession(824177287)--Thread(Thread[main,5,main])--Execute query ValueReadQuery(name="ID_SEQ_GEN" sql="SELECT LAST_INSERT_ID()") [EL Fine]: sql: 2014-10-19 06:44:02.608--ClientSession(824177287)--Connection(1674390738)--Thread(Thread[main,5,main])--INSERT INTO ENTITYCLASSTEST (LASTNAME, NAME) VALUES (?, ?) bind => [sfirosijfhgdoi 2068, dsufius1034] [EL Fine]: sql: 2014-10-19 06:44:02.608--ClientSession(824177287)--Connection(1674390738)--Thread(Thread[main,5,main])--SELECT LAST_INSERT_ID() [EL Finest]: sequencing: 2014-10-19 06:44:02.608--UnitOfWork(1985011414)--Thread(Thread[main,5,main])--assign sequence to the object (1.252 -> database.EntityClassTest [id=null ]) [EL Finest]: query: 2014-10-19 06:44:02.608--UnitOfWork(1985011414)--Thread(Thread[main,5,main])--Execute query InsertObjectQuery(database.EntityClassTest [id=null ]) [EL Finest]: query: 2014-10-19 06:44:02.608--ClientSession(824177287)--Thread(Thread[main,5,main])--Execute query ValueReadQuery(name="ID_SEQ_GEN" sql="SELECT LAST_INSERT_ID()") [EL Fine]: sql: 2014-10-19 06:44:02.608--ClientSession(824177287)--Connection(1674390738)--Thread(Thread[main,5,main])--INSERT INTO ENTITYCLASSTEST (LASTNAME, NAME) VALUES (?, ?) bind => [sfirosijfhgdoi 2244, dsufius1122]
Etc...