mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
167 lines
4.4 KiB
Java
167 lines
4.4 KiB
Java
package com.avaje.ebeaninternal.server.persist;
|
|
|
|
import com.avaje.ebeaninternal.server.core.PersistRequest;
|
|
import com.avaje.ebeaninternal.server.core.PersistRequestBean;
|
|
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.IdentityHashMap;
|
|
|
|
/**
|
|
* Holds lists of persist requests for beans of a given type.
|
|
* <p>
|
|
* This is used to delay the actual binding of the bean to PreparedStatements.
|
|
* The reason is that we don't have all the bind values yet in the case of inserts
|
|
* with getGeneratedKeys.
|
|
* </p>
|
|
* <p>
|
|
* Has a depth which is used to determine the order in which it should be
|
|
* executed. The lowest depth is executed first.
|
|
* </p>
|
|
*/
|
|
public class BatchedBeanHolder {
|
|
|
|
private static final Object DUMMY = new Object();
|
|
|
|
/**
|
|
* The owning queue.
|
|
*/
|
|
private final BatchControl control;
|
|
|
|
private final String shortDesc;
|
|
|
|
/**
|
|
* The 'depth' which is used to determine the execution order.
|
|
*/
|
|
private final int order;
|
|
|
|
/**
|
|
* The list of bean insert requests.
|
|
*/
|
|
private ArrayList<PersistRequest> inserts;
|
|
|
|
/**
|
|
* The list of bean update requests.
|
|
*/
|
|
private ArrayList<PersistRequest> updates;
|
|
|
|
/**
|
|
* The list of bean delete requests.
|
|
*/
|
|
private ArrayList<PersistRequest> deletes;
|
|
|
|
/**
|
|
* Set of beans in this batch. This is used to ensure that a single bean instance is not included
|
|
* in the batch twice (two separate insert requests etc).
|
|
*/
|
|
private final IdentityHashMap<Object, Object> persistedBeans = new IdentityHashMap<Object, Object>();
|
|
|
|
/**
|
|
* Create a new entry with a given type and depth.
|
|
*/
|
|
public BatchedBeanHolder(BatchControl control, BeanDescriptor<?> beanDescriptor, int order) {
|
|
this.control = control;
|
|
this.shortDesc = beanDescriptor.getName() + ":" + order;
|
|
this.order = order;
|
|
}
|
|
|
|
/**
|
|
* Return the depth.
|
|
*/
|
|
public int getOrder() {
|
|
return order;
|
|
}
|
|
|
|
/**
|
|
* Execute all the persist requests in this entry.
|
|
* <p>
|
|
* This will Batch all the similar requests into one or more BatchStatements
|
|
* and then execute them.
|
|
* </p>
|
|
*/
|
|
public void executeNow() {
|
|
// process the requests. Creates one or more PreparedStatements
|
|
// with binding addBatch() for each request.
|
|
// Note updates and deletes can result in many PreparedStatements
|
|
// if their where clauses differ via use of IS NOT NULL.
|
|
if (inserts != null && !inserts.isEmpty()) {
|
|
control.executeNow(inserts);
|
|
inserts.clear();
|
|
}
|
|
if (updates != null && !updates.isEmpty()) {
|
|
control.executeNow(updates);
|
|
updates.clear();
|
|
}
|
|
if (deletes != null && !deletes.isEmpty()) {
|
|
control.executeNow(deletes);
|
|
deletes.clear();
|
|
}
|
|
persistedBeans.clear();
|
|
}
|
|
|
|
public String toString() {
|
|
StringBuilder sb = new StringBuilder(shortDesc.length() + 18);
|
|
sb.append(shortDesc);
|
|
if (inserts != null) {
|
|
sb.append(" i:").append(inserts.size());
|
|
}
|
|
if (updates != null) {
|
|
sb.append(" u:").append(updates.size());
|
|
}
|
|
if (deletes != null) {
|
|
sb.append(" d:").append(deletes.size());
|
|
}
|
|
return sb.toString();
|
|
}
|
|
|
|
/**
|
|
* Add the request to the appropriate persist list.
|
|
*/
|
|
public int append(PersistRequestBean<?> request) {
|
|
|
|
Object alreadyInBatch = persistedBeans.put(request.getEntityBean(), DUMMY);
|
|
if (alreadyInBatch != null) {
|
|
// special case where the same bean instance has already been
|
|
// added to the batch (doesn't really occur with non-batching
|
|
// as the bean gets changed from dirty to loaded earlier)
|
|
return 0;
|
|
}
|
|
|
|
request.setBatched();
|
|
|
|
switch (request.getType()) {
|
|
case INSERT:
|
|
if (inserts == null) {
|
|
inserts = new ArrayList<PersistRequest>();
|
|
}
|
|
inserts.add(request);
|
|
return inserts.size();
|
|
|
|
case UPDATE:
|
|
case SOFT_DELETE:
|
|
if (updates == null) {
|
|
updates = new ArrayList<PersistRequest>();
|
|
}
|
|
updates.add(request);
|
|
return updates.size();
|
|
|
|
case DELETE:
|
|
if (deletes == null) {
|
|
deletes = new ArrayList<PersistRequest>();
|
|
}
|
|
deletes.add(request);
|
|
return deletes.size();
|
|
|
|
default:
|
|
throw new RuntimeException("Invalid type code " + request.getType());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Return true if this is empty containing no batched beans.
|
|
*/
|
|
public boolean isEmpty() {
|
|
return persistedBeans.isEmpty();
|
|
}
|
|
}
|