#始めに
業務で必要になりそうなので、EclipseLinkを使ってDBプログラミングをしてみた
#サンプルプログラム
1の連番をDBにインサートするプログラムを書いてみた
InsertLogic.java
package logic;
import java.util.Date;
import java.util.stream.Stream;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import entiry.SequeceNum;
public class InsertLogic {
public static void main(String args[]){
new InsertLogic().doLogic();
}
public void doLogic(){
EntityManagerFactory factory = Persistence.createEntityManagerFactory("myUnitInPersistenceXML");
EntityManager em = factory.createEntityManager();
long start =System.currentTimeMillis();
System.out.println("insert start");
em.getTransaction().begin();
Stream.iterate(1l, s->s+1)
.limit(1000000000000l)
.map(i->createSequeceNum(i))
.forEach(o->doInsert(em,o));
System.out.println("insert End");
long ends =System.currentTimeMillis();
System.out.println(String.format("かかった時間 %d", (ends - start)));
}
private static SequeceNum createSequeceNum(long i){
SequeceNum myEntity = new SequeceNum();
myEntity.setId(i);
return myEntity;
}
private static void doInsert(EntityManager em,SequeceNum entity){
em.persist(entity);
if(entity.getId()%100000 == 0){
em.getTransaction().commit();
em.getTransaction().begin();
}
}
}
SequeceNum.java
package entiry;
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class SequeceNum {
@Id
private long id;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
}
このまま実行すると、以下のエラーがでる
[EL Info]: 2017-12-03 21:56:37.505--ServerSession(336400944)--EclipseLink, version: Eclipse Persistence Services - 2.5.1.v20130918-f2b9fc5
[EL Info]: connection: 2017-12-03 21:56:38.156--ServerSession(336400944)--file:/C:/Users/takayoshi/workspace/Pazzle/bin/_myUnitInPersistenceXML login successful
insert start
Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
at org.eclipse.persistence.internal.descriptors.ObjectBuilder.createObjectChangeSet(ObjectBuilder.java:2872)
at org.eclipse.persistence.descriptors.changetracking.DeferredChangeDetectionPolicy.createObjectChangeSetThroughComparison(DeferredChangeDetectionPolicy.java:155)
at org.eclipse.persistence.descriptors.changetracking.DeferredChangeDetectionPolicy.createObjectChangeSet(DeferredChangeDetectionPolicy.java:146)
at org.eclipse.persistence.descriptors.changetracking.DeferredChangeDetectionPolicy.calculateChanges(DeferredChangeDetectionPolicy.java:91)
at org.eclipse.persistence.descriptors.changetracking.DeferredChangeDetectionPolicy.calculateChangesForExistingObject(DeferredChangeDetectionPolicy.java:56)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.calculateChanges(UnitOfWorkImpl.java:664)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1516)
at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitRootUnitOfWork(RepeatableWriteUnitOfWork.java:277)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitAndResume(UnitOfWorkImpl.java:1169)
at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:132)
at logic.InsertLogic.doInsert(InsertLogic.java:43)
at logic.InsertLogic.lambda$2(InsertLogic.java:28)
at logic.InsertLogic$$Lambda$6/2137034273.accept(Unknown Source)
at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(Unknown Source)
at java.util.stream.ReferencePipeline$3$1.accept(Unknown Source)
at java.util.stream.SliceOps$1$1.accept(Unknown Source)
at java.util.Spliterators$IteratorSpliterator.tryAdvance(Unknown Source)
at java.util.stream.ReferencePipeline.forEachWithCancel(Unknown Source)
at java.util.stream.AbstractPipeline.copyIntoWithCancel(Unknown Source)
at java.util.stream.AbstractPipeline.copyInto(Unknown Source)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(Unknown Source)
at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(Unknown Source)
at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(Unknown Source)
at java.util.stream.AbstractPipeline.evaluate(Unknown Source)
at java.util.stream.ReferencePipeline.forEach(Unknown Source)
at logic.InsertLogic.doLogic(InsertLogic.java:28)
at logic.InsertLogic.main(InsertLogic.java:15)
[EL Info]: connection: 2017-12-03 22:23:39.469--ServerSession(336400944)--file:/C:/Users/takayoshi/workspace/Pazzle/bin/_myUnitInPersistenceXML logout successful
どうやら、メモリに実行した結果がキャッシュに残っているらしく、ヒープ領域が枯渇したようだ
ちなみに、ヒープが枯渇した時にDBにインサートした行数は以下の通り
COUNT(*)
----------
2400001
どうやら、何の工夫もなくInsert文を実行するとシンプルなデータ構造でも25万件程度でエラーが発生するらしい
改善案は次のエントリで書いてみる