質問

I am trying to do a batch persist using JPA/EclipseLink 2.4.1 and MSSQL Server using Merlia drivers. Based on the way the database reacts along with the logs (below), it appears that each insert happens within its own batch.

I have set the persistence xml up as follows:

<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
  <persistence-unit name="EclipseLinkPersistenceUnit">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <class>com.mypackage.ViewInDatabaseEntity</class>
    ...
    <exclude-unlisted-classes>true</exclude-unlisted-classes>
    <properties>
      <property name="javax.persistence.jdbc.driver" value="com.inet.tds.PDataSource4"/>
      <property name="eclipselink.jdbc.batch-writing" value="jdbc" />
      <property name="eclipselink.jdbc.batch-writing.size" value="1000" />
      <property name="eclipselink.logging.level" value="FINEST"/>
    </properties>
  </persistence-unit>
</persistence>

The code calling the persist looks like this. I normally use the @Transactional but decided to manually begin and commit the transactions to ensure that the annotation was not doing something unexpected under the hood.

  //@Transactional
  public void persistEntity(List<ViewInDatabaseEntity> entitiesToPersist) {
    EntityManager entityManager = entityManagerProvider.get();
    entityManager.setFlushMode(FlushModeType.COMMIT);
    EntityTransaction transaction = entityManager.getTransaction();
    transaction.begin();

    for (ViewInDatabaseEntity entity : entitiesToPersist) {
      entityManager.persist(entity);
    }

    transaction.commit();
  }

The logs (set to FINEST) are outputting:

[EL Finer]: transaction: 2014-05-02 16:42:49.963--ClientSession(27801544)--Connection(28732068)--Thread(Thread[qtp18824904-22,5,main])--begin transaction
...
[EL Finest]: query: 2014-05-02 16:42:49.964--ClientSession(27801544)--Thread(Thread[qtp18824904-22,5,main])--Execute query ValueReadQuery(name="SEQ_GEN_SEQUENCE" sql="SELECT @@IDENTITY")
[EL Finer]: sql: 2014-05-02 16:42:56.422--ClientSession(27801544)--Connection(28732068)--Thread(Thread[qtp18824904-22,5,main])--Begin batch statements
[EL Fine]: sql: 2014-05-02 16:42:56.422--ClientSession(27801544)--Connection(28732068)--Thread(Thread[qtp18824904-22,5,main])--INSERT INTO dbo.ViewInDatabaseEntity(property1, property4, property3, property2, property5) VALUES (?, ?, ?, ?, ?)
[EL Fine]: sql: 2014-05-02 16:42:56.422--ClientSession(27801544)--Connection(28732068)--Thread(Thread[qtp18824904-22,5,main])-- bind => [ABC, DEF, GHI, JKL, 0.3465443]
[EL Finer]: sql: 2014-05-02 16:42:56.422--ClientSession(27801544)--Connection(28732068)--Thread(Thread[qtp18824904-22,5,main])--End Batch Statements
[EL Fine]: sql: 2014-05-02 16:42:56.505--ClientSession(27801544)--Connection(28732068)--Thread(Thread[qtp18824904-22,5,main])--SELECT @@IDENTITY
[EL Finest]: sequencing: 2014-05-02 16:42:56.506--UnitOfWork(15091453)--Thread(Thread[qtp18824904-22,5,main])--assign sequence to the object (89,588 -> com.mypackage.ViewInDatabaseEntity@945ed6f5)
[EL Finest]: query: 2014-05-02 16:42:56.507--UnitOfWork(15091453)--Thread(Thread[qtp18824904-22,5,main])--Execute query InsertObjectQuery(com.mypackage.ViewInDatabaseEntity@5d6e305d)
[EL Finest]: query: 2014-05-02 16:42:56.507--ClientSession(27801544)--Thread(Thread[qtp18824904-22,5,main])--Execute query ValueReadQuery(name="SEQ_GEN_SEQUENCE" sql="SELECT @@IDENTITY")
[EL Finer]: sql: 2014-05-02 16:42:56.507--ClientSession(27801544)--Connection(28732068)--Thread(Thread[qtp18824904-22,5,main])--Begin batch statements
[EL Fine]: sql: 2014-05-02 16:42:56.507--ClientSession(27801544)--Connection(28732068)--Thread(Thread[qtp18824904-22,5,main])--INSERT INTO dbo.ViewInDatabaseEntity(property1, property4, property3, property2, property5) VALUES (?, ?, ?, ?, ?)
[EL Fine]: sql: 2014-05-02 16:42:56.507--ClientSession(27801544)--Connection(28732068)--Thread(Thread[qtp18824904-22,5,main])-- bind => [ABC, ZYX, WVU, RST, 0.35345634]
[EL Finer]: sql: 2014-05-02 16:42:56.507--ClientSession(27801544)--Connection(28732068)--Thread(Thread[qtp18824904-22,5,main])--End Batch Statements
[EL Fine]: sql: 2014-05-02 16:42:56.591--ClientSession(27801544)--Connection(28732068)--Thread(Thread[qtp18824904-22,5,main])--SELECT @@IDENTITY
[EL Finest]: sequencing: 2014-05-02 16:42:56.592--UnitOfWork(15091453)--Thread(Thread[qtp18824904-22,5,main])--assign sequence to the object (89,666 -> com.mypackage.ViewInDatabaseEntity@5d6e305d)
...
[EL Finer]: transaction: 2014-05-02 16:42:56.598--ClientSession(27801544)--Connection(28732068)--Thread(Thread[qtp18824904-22,5,main])--commit transaction
[EL Finest]: connection: 2014-05-02 16:42:56.605--ServerSession(2644459)--Connection(28732068)--Thread(Thread[qtp18824904-22,5,main])--Connection released to connection pool [default].

This seems to indicate that each of the inserts is happening within its own batch. As per the persistence.xml; I have enabled

<property name="eclipselink.jdbc.batch-writing" value="jdbc" />

So as far as I am aware, these inserts should be happening as a batch. The following is the entity I am trying to persist. It exists as a View overlaying several underlying tables in the MSSQL Server DB.

@javax.persistence.Table(name = "ViewInDatabase", schema = "dbo")
@Entity
@EqualsAndHashCode
@Getter
@Setter
public class ViewInDatabaseEntity {

  @Id
  @GeneratedValue(strategy = GenerationType.SEQUENCE)
  private int id;

  @javax.persistence.Column(name = "id", nullable = false, insertable = false, updatable = false,
        length = 0, precision = 0)
  @Basic
  public int getId() {
    return id;
  }

  @javax.persistence.Column(name = "property1", nullable = false, insertable = true,
        updatable = true, length = 20, precision = 0)
  @Basic
  private String property1;

  @javax.persistence.Column(name = "property2", nullable = true, insertable = true, updatable = true,
        length = 0, precision = 0)
  @Basic
  private String property2;

  @javax.persistence.Column(name = "property3", nullable = true, insertable = true,
        updatable = true, length = 0, precision = 0)
  @Basic
  private String property3;

  @javax.persistence.Column(name = "property4", nullable = false, insertable = true, updatable = true,
        length = 10, precision = 0)
  @Basic
  private String property4;

  @javax.persistence.Column(name = "property5", nullable = true, insertable = true, updatable = true,
        length = 0, precision = 0)
  @Basic
  private BigDecimal property5;

  @javax.persistence.Column(name = "property6", nullable = false, insertable = false,
        updatable = false, length = 0, precision = 0)
  @Basic
  private int property6;

  @javax.persistence.Column(name = "property7", nullable = false, insertable = false,
        updatable = false, length = 0, precision = 0)
  @Basic
  private Date property7;
}
役に立ちましたか?

解決

Batching will not work when the sequence strategy requires looking up the assigned sequence value after each insert statement. Try using table sequencing or some strategy that allows assigning sequence values upfront so that they can be batched.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top