mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Initial experimental support for "transparent persistence"
In short, when this is turned on at flush() get any dirty beans held by the PersistenceContext and persist them (always update for these beans)
This commit is contained in:
@@ -131,6 +131,11 @@ public class ScopedTransaction extends SpiTransactionProxy {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTransparentPersistence(boolean transparentPersistence) {
|
||||
current.getTransaction().setTransparentPersistence(transparentPersistence);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRollbackOnly() {
|
||||
current.setRollbackOnly();
|
||||
|
||||
@@ -236,7 +236,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
this.clockService = config.getClockService();
|
||||
|
||||
DocStoreIntegration docStoreComponents = config.createDocStoreIntegration(this);
|
||||
this.transactionManager = config.createTransactionManager(docStoreComponents.updateProcessor());
|
||||
this.transactionManager = config.createTransactionManager(this, docStoreComponents.updateProcessor());
|
||||
this.documentStore = docStoreComponents.documentStore();
|
||||
this.queryPlanManager = config.initQueryPlanManager(transactionManager);
|
||||
this.metaInfoManager = new DefaultMetaInfoManager(this);
|
||||
|
||||
@@ -423,13 +423,13 @@ public class InternalConfiguration {
|
||||
/**
|
||||
* Create the TransactionManager taking into account autoCommit mode.
|
||||
*/
|
||||
TransactionManager createTransactionManager(DocStoreUpdateProcessor indexUpdateProcessor) {
|
||||
TransactionManager createTransactionManager(SpiServer server, DocStoreUpdateProcessor indexUpdateProcessor) {
|
||||
|
||||
TransactionScopeManager scopeManager = createTransactionScopeManager();
|
||||
boolean notifyL2CacheInForeground = cacheManager.isLocalL2Caching() || config.isNotifyL2CacheInForeground();
|
||||
|
||||
TransactionManagerOptions options =
|
||||
new TransactionManagerOptions(notifyL2CacheInForeground, config, scopeManager, clusterManager, backgroundExecutor,
|
||||
new TransactionManagerOptions(server, notifyL2CacheInForeground, config, scopeManager, clusterManager, backgroundExecutor,
|
||||
indexUpdateProcessor, beanDescriptorManager, dataSource(), profileHandler(), logManager,
|
||||
tableModState, cacheNotify, clockService);
|
||||
|
||||
|
||||
+27
-4
@@ -1,11 +1,9 @@
|
||||
package io.ebeaninternal.server.transaction;
|
||||
|
||||
import io.ebean.bean.EntityBean;
|
||||
import io.ebean.bean.PersistenceContext;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
@@ -200,6 +198,20 @@ public final class DefaultPersistenceContext implements PersistenceContext {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Object> dirtyBeans() {
|
||||
lock.lock();
|
||||
try {
|
||||
List<Object> list = new ArrayList<>();
|
||||
for (ClassContext classContext : typeCache.values()) {
|
||||
classContext.dirtyBeans(list);
|
||||
}
|
||||
return list;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
lock.lock();
|
||||
@@ -318,6 +330,17 @@ public final class DefaultPersistenceContext implements PersistenceContext {
|
||||
deleteSet.add(id);
|
||||
map.remove(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the dirty beans to the list.
|
||||
*/
|
||||
void dirtyBeans(List<Object> list) {
|
||||
for (Object value : map.values()) {
|
||||
if (((EntityBean) value)._ebean_getIntercept().isDirty()) {
|
||||
list.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+5
@@ -95,6 +95,11 @@ class ImplicitReadOnlyTransaction implements SpiTransaction, TxnProfileEventCode
|
||||
return startNanos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTransparentPersistence(boolean transparentPersistence) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLabel(String label) {
|
||||
// do nothing
|
||||
|
||||
@@ -187,6 +187,8 @@ class JdbcTransaction implements SpiTransaction, TxnProfileEventCodes {
|
||||
|
||||
private final long startNanos;
|
||||
|
||||
private boolean transparentPersistence;
|
||||
|
||||
/**
|
||||
* Create a new JdbcTransaction.
|
||||
*/
|
||||
@@ -294,6 +296,12 @@ class JdbcTransaction implements SpiTransaction, TxnProfileEventCodes {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTransparentPersistence(boolean transparentPersistence) {
|
||||
this.transparentPersistence = transparentPersistence;
|
||||
this.batchMode = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSkipCacheExplicit() {
|
||||
return (skipCache != null && !skipCache);
|
||||
@@ -774,6 +782,10 @@ class JdbcTransaction implements SpiTransaction, TxnProfileEventCodes {
|
||||
* Flush the JDBC batch and execute derived relationship statements if necessary.
|
||||
*/
|
||||
private void internalBatchFlush() {
|
||||
if (transparentPersistence) {
|
||||
// Experimental - flush dirty beans held by the persistence context
|
||||
manager.flushTransparent(persistenceContext, this);
|
||||
}
|
||||
batchFlush();
|
||||
if (deferredList != null) {
|
||||
for (PersistDeferredRelationship deferred : deferredList) {
|
||||
@@ -1042,7 +1054,7 @@ class JdbcTransaction implements SpiTransaction, TxnProfileEventCodes {
|
||||
throw new IllegalStateException(illegalStateMessage);
|
||||
}
|
||||
try {
|
||||
if (queryOnly) {
|
||||
if (queryOnly && !transparentPersistence) {
|
||||
connectionEndForQueryOnly();
|
||||
} else {
|
||||
flushCommitAndNotify();
|
||||
|
||||
@@ -25,6 +25,11 @@ class NoTransaction implements SpiTransaction {
|
||||
|
||||
static final NoTransaction INSTANCE = new NoTransaction();
|
||||
|
||||
@Override
|
||||
public void setTransparentPersistence(boolean transparentPersistence) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLabel(String label) {
|
||||
// do nothing
|
||||
|
||||
@@ -60,6 +60,11 @@ class SavepointTransaction extends SpiTransactionProxy {
|
||||
this.rollbackOnly = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTransparentPersistence(boolean transparentPersistence) {
|
||||
throw new IllegalStateException("This is not handled yet. Need to review this case.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commit() {
|
||||
if (rollbackOnly) {
|
||||
|
||||
+15
-1
@@ -5,6 +5,7 @@ import io.ebean.ProfileLocation;
|
||||
import io.ebean.TxScope;
|
||||
import io.ebean.annotation.PersistBatch;
|
||||
import io.ebean.annotation.TxType;
|
||||
import io.ebean.bean.PersistenceContext;
|
||||
import io.ebean.cache.ServerCacheNotification;
|
||||
import io.ebean.cache.ServerCacheNotify;
|
||||
import io.ebean.config.CurrentTenantProvider;
|
||||
@@ -17,6 +18,7 @@ import io.ebean.meta.MetricVisitor;
|
||||
import io.ebean.metric.MetricFactory;
|
||||
import io.ebean.metric.TimedMetric;
|
||||
import io.ebean.metric.TimedMetricMap;
|
||||
import io.ebean.plugin.SpiServer;
|
||||
import io.ebeaninternal.api.ScopeTrans;
|
||||
import io.ebeaninternal.api.ScopedTransaction;
|
||||
import io.ebeaninternal.api.SpiLogManager;
|
||||
@@ -59,6 +61,8 @@ public class TransactionManager implements SpiTransactionManager {
|
||||
|
||||
private static final Logger clusterLogger = LoggerFactory.getLogger("io.ebean.Cluster");
|
||||
|
||||
private final SpiServer server;
|
||||
|
||||
private final BeanDescriptorManager beanDescriptorManager;
|
||||
|
||||
/**
|
||||
@@ -153,7 +157,7 @@ public class TransactionManager implements SpiTransactionManager {
|
||||
* Create the TransactionManager
|
||||
*/
|
||||
public TransactionManager(TransactionManagerOptions options) {
|
||||
|
||||
this.server = options.server;
|
||||
this.logManager = options.logManager;
|
||||
this.txnLogger = logManager.txn();
|
||||
this.txnDebug = txnLogger.isDebug();
|
||||
@@ -786,4 +790,14 @@ public class TransactionManager implements SpiTransactionManager {
|
||||
public boolean isLogSummary() {
|
||||
return logManager.sum().isDebug();
|
||||
}
|
||||
|
||||
/**
|
||||
* Experimental - find dirty beans in the persistence context and persist them.
|
||||
*/
|
||||
public void flushTransparent(PersistenceContext persistenceContext, SpiTransaction transaction) {
|
||||
List<Object> dirtyBeans = persistenceContext.dirtyBeans();
|
||||
if (!dirtyBeans.isEmpty()) {
|
||||
server.updateAll(dirtyBeans, transaction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-2
@@ -3,6 +3,7 @@ package io.ebeaninternal.server.transaction;
|
||||
import io.ebean.BackgroundExecutor;
|
||||
import io.ebean.cache.ServerCacheNotify;
|
||||
import io.ebean.config.DatabaseConfig;
|
||||
import io.ebean.plugin.SpiServer;
|
||||
import io.ebeaninternal.api.SpiLogManager;
|
||||
import io.ebeaninternal.api.SpiProfileHandler;
|
||||
import io.ebeaninternal.server.cluster.ClusterManager;
|
||||
@@ -15,6 +16,7 @@ import io.ebeanservice.docstore.api.DocStoreUpdateProcessor;
|
||||
*/
|
||||
public class TransactionManagerOptions {
|
||||
|
||||
final SpiServer server;
|
||||
final boolean notifyL2CacheInForeground;
|
||||
final DatabaseConfig config;
|
||||
final ClusterManager clusterManager;
|
||||
@@ -31,11 +33,11 @@ public class TransactionManagerOptions {
|
||||
final ClockService clockService;
|
||||
|
||||
|
||||
public TransactionManagerOptions(boolean notifyL2CacheInForeground, DatabaseConfig config, TransactionScopeManager scopeManager, ClusterManager clusterManager,
|
||||
public TransactionManagerOptions(SpiServer server, boolean notifyL2CacheInForeground, DatabaseConfig config, TransactionScopeManager scopeManager, ClusterManager clusterManager,
|
||||
BackgroundExecutor backgroundExecutor, DocStoreUpdateProcessor docStoreUpdateProcessor,
|
||||
BeanDescriptorManager descMgr, DataSourceSupplier dataSourceSupplier, SpiProfileHandler profileHandler,
|
||||
SpiLogManager logManager, TableModState tableModState, ServerCacheNotify cacheNotify, ClockService clockService) {
|
||||
|
||||
this.server = server;
|
||||
this.notifyL2CacheInForeground = notifyL2CacheInForeground;
|
||||
this.config = config;
|
||||
this.scopeManager = scopeManager;
|
||||
|
||||
Reference in New Issue
Block a user