diff --git a/src/main/java/com/avaje/ebean/annotation/CacheStrategy.java b/src/main/java/com/avaje/ebean/annotation/Cache.java similarity index 50% rename from src/main/java/com/avaje/ebean/annotation/CacheStrategy.java rename to src/main/java/com/avaje/ebean/annotation/Cache.java index ded62462b..bce44cc6d 100644 --- a/src/main/java/com/avaje/ebean/annotation/CacheStrategy.java +++ b/src/main/java/com/avaje/ebean/annotation/Cache.java @@ -5,25 +5,36 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import com.avaje.ebean.Query; - /** * Specify the default cache use specific entity type. */ @Target({ ElementType.TYPE }) @Retention(RetentionPolicy.RUNTIME) -public @interface CacheStrategy { +public @interface Cache { /** - * When set to true the bean cache will be used unless explicitly stated not - * to in a query via {@link Query#setUseCache(boolean)}. - */ - boolean useBeanCache() default true; - - /** - * A single property that is a natural unique identifier for the bean. + * Set this to true to enable the use of query cache. *

- * When a findUnique query is used with this property as the sole expression + * By default query caching is disabled as the query cache invalidates + * frequently and so it is typically used for specific bean types and cases. + *

+ */ + boolean enableQueryCache() default false; + + /** + * Set this to false to disable the use of bean cache. + *

+ * By default bean caching is expected so this defaults to true. We might + * set this to false on a bean type that we want to use query caching but no + * bean caching (and this is expected to be a rare case). + *

+ */ + boolean enableBeanCache() default true; + + /** + * Specify the property that is a natural unique identifier for the bean. + *

+ * When a findUnique() query is used with this property as the sole expression * then there will be a lookup into the L2 natural key cache. *

*/ diff --git a/src/main/java/com/avaje/ebean/cache/ServerCache.java b/src/main/java/com/avaje/ebean/cache/ServerCache.java index 195446c20..e3c64a326 100644 --- a/src/main/java/com/avaje/ebean/cache/ServerCache.java +++ b/src/main/java/com/avaje/ebean/cache/ServerCache.java @@ -1,7 +1,5 @@ package com.avaje.ebean.cache; -import com.avaje.ebean.EbeanServer; - /** * Represents part of the "L2" server side cache. *

@@ -17,27 +15,6 @@ import com.avaje.ebean.EbeanServer; */ public interface ServerCache { - /** - * Just after a cache is created this init method is called. This is so that a - * cache implementation can make use of the BackgroundExecutor service to - * trim/cleanup itself or use the EbeanServer to populate itself. - *

- * This method is called after the cache is constructed but before the cache - * is made available for use. - *

- */ - void init(EbeanServer ebeanServer); - - /** - * Return the configuration options for this cache. - */ - ServerCacheOptions getOptions(); - - /** - * Update the configuration options for this cache. - */ - void setOptions(ServerCacheOptions options); - /** * Return the value given the key. */ diff --git a/src/main/java/com/avaje/ebean/cache/ServerCacheFactory.java b/src/main/java/com/avaje/ebean/cache/ServerCacheFactory.java index 4c913a729..01310c4ee 100644 --- a/src/main/java/com/avaje/ebean/cache/ServerCacheFactory.java +++ b/src/main/java/com/avaje/ebean/cache/ServerCacheFactory.java @@ -1,23 +1,10 @@ package com.avaje.ebean.cache; -import com.avaje.ebean.EbeanServer; - /** * Defines method for constructing caches for beans and queries. */ public interface ServerCacheFactory { - /** - * Just after the ServerCacheFactory is constructed this method is called - * passing the EbeanServer. - *

- * This is so that a cache implementation can utilise the EbeanServer to - * populate itself or use the BackgroundExecutor service to schedule periodic - * cache trimming/cleanup. - *

- */ - void init(EbeanServer ebeanServer); - /** * Create the cache for the given type with options. */ diff --git a/src/main/java/com/avaje/ebean/cache/ServerCacheManager.java b/src/main/java/com/avaje/ebean/cache/ServerCacheManager.java index 3e08718c2..50bcffceb 100644 --- a/src/main/java/com/avaje/ebean/cache/ServerCacheManager.java +++ b/src/main/java/com/avaje/ebean/cache/ServerCacheManager.java @@ -1,25 +1,10 @@ package com.avaje.ebean.cache; -import com.avaje.ebean.EbeanServer; - /** * The cache service for server side caching of beans and query results. */ public interface ServerCacheManager { - /** - * This method is called just after the construction of the - * ServerCacheManager. - *

- * The EbeanServer is provided so that cache implementations can make use of - * EbeanServer and BackgroundExecutor for automatically populating and - * background trimming of the cache. - *

- */ - void init(EbeanServer server); - - void setCaching(Class beanType, boolean useCache); - /** * Return true if there is an active bean cache for this type of bean. */ @@ -35,6 +20,9 @@ public interface ServerCacheManager { */ ServerCache getBeanCache(Class beanType); + /** + * Return the cache for associated many properties of a bean type. + */ ServerCache getCollectionIdsCache(Class beanType, String propertyName); /** diff --git a/src/main/java/com/avaje/ebean/cache/ServerCachePlugin.java b/src/main/java/com/avaje/ebean/cache/ServerCachePlugin.java new file mode 100644 index 000000000..2fe635d1c --- /dev/null +++ b/src/main/java/com/avaje/ebean/cache/ServerCachePlugin.java @@ -0,0 +1,15 @@ +package com.avaje.ebean.cache; + +import com.avaje.ebean.BackgroundExecutor; +import com.avaje.ebean.config.ServerConfig; + +/** + * The plugin interface that creates a ServerCacheFactory. + */ +public interface ServerCachePlugin { + + /** + * Create the ServerCacheFactory given the server config and background executor service. + */ + ServerCacheFactory create(ServerConfig config, BackgroundExecutor executor); +} diff --git a/src/main/java/com/avaje/ebean/config/ServerConfig.java b/src/main/java/com/avaje/ebean/config/ServerConfig.java index f1c12a2e7..f3d4ab5c9 100644 --- a/src/main/java/com/avaje/ebean/config/ServerConfig.java +++ b/src/main/java/com/avaje/ebean/config/ServerConfig.java @@ -5,6 +5,7 @@ import com.avaje.ebean.PersistenceContextScope; import com.avaje.ebean.annotation.Encrypted; import com.avaje.ebean.cache.ServerCacheFactory; import com.avaje.ebean.cache.ServerCacheManager; +import com.avaje.ebean.cache.ServerCachePlugin; import com.avaje.ebean.config.dbplatform.DatabasePlatform; import com.avaje.ebean.config.dbplatform.DbEncrypt; import com.avaje.ebean.event.BeanFindController; @@ -356,7 +357,7 @@ public class ServerConfig { private DbEncrypt dbEncrypt; - private ServerCacheFactory serverCacheFactory; + private ServerCachePlugin serverCachePlugin; private ServerCacheManager serverCacheManager; @@ -938,17 +939,17 @@ public class ServerConfig { } /** - * Return the ServerCacheFactory. + * Return the ServerCachePlugin. */ - public ServerCacheFactory getServerCacheFactory() { - return serverCacheFactory; + public ServerCachePlugin getServerCachePlugin() { + return serverCachePlugin; } /** - * Set the ServerCacheFactory to use. + * Set the ServerCachePlugin to use. */ - public void setServerCacheFactory(ServerCacheFactory serverCacheFactory) { - this.serverCacheFactory = serverCacheFactory; + public void setServerCachePlugin(ServerCachePlugin serverCachePlugin) { + this.serverCachePlugin = serverCachePlugin; } /** @@ -2352,7 +2353,7 @@ public class ServerConfig { encryptDeployManager = createInstance(p, EncryptDeployManager.class, "encryptDeployManager", encryptDeployManager); encryptor = createInstance(p, Encryptor.class, "encryptor", encryptor); dbEncrypt = createInstance(p, DbEncrypt.class, "dbEncrypt", dbEncrypt); - serverCacheFactory = createInstance(p, ServerCacheFactory.class, "serverCacheFactory", serverCacheFactory); + serverCachePlugin = createInstance(p, ServerCachePlugin.class, "serverCachePlugin", serverCachePlugin); serverCacheManager = createInstance(p, ServerCacheManager.class, "serverCacheManager", serverCacheManager); cacheWarmingDelay = p.getInt("cacheWarmingDelay", cacheWarmingDelay); classPathReaderClassName = p.get("classpathreader"); diff --git a/src/main/java/com/avaje/ebean/dbmigration/model/visitor/VisitAllUsing.java b/src/main/java/com/avaje/ebean/dbmigration/model/visitor/VisitAllUsing.java index a2966c119..f8f415db1 100644 --- a/src/main/java/com/avaje/ebean/dbmigration/model/visitor/VisitAllUsing.java +++ b/src/main/java/com/avaje/ebean/dbmigration/model/visitor/VisitAllUsing.java @@ -150,8 +150,8 @@ public class VisitAllUsing { } public void visit(InheritInfo inheritInfo) { - BeanProperty[] propertiesLocal = inheritInfo.getBeanDescriptor().propertiesLocal(); - for (int i = 0; i desc, EntityBean bean, CachedBeanData cacheBeanData) { + public static void load(BeanDescriptor desc, EntityBean bean, CachedBeanData cacheBeanData, PersistenceContext context) { EntityBeanIntercept ebi = bean._ebean_getIntercept(); BeanProperty idProperty = desc.getIdProperty(); if (idProperty != null) { // load the id property - loadProperty(bean, cacheBeanData, ebi, idProperty); + loadProperty(bean, cacheBeanData, ebi, idProperty, context); } // load the non-many properties BeanProperty[] props = desc.propertiesNonMany(); for (int i = 0; i < props.length; i++) { - loadProperty(bean, cacheBeanData, ebi, props[i]); + loadProperty(bean, cacheBeanData, ebi, props[i], context); } BeanPropertyAssocMany[] many = desc.propertiesMany(); @@ -33,12 +34,12 @@ public class CachedBeanDataToBean { ebi.setLoadedLazy(); } - private static void loadProperty(EntityBean bean, CachedBeanData cacheBeanData, EntityBeanIntercept ebi, BeanProperty prop) { + private static void loadProperty(EntityBean bean, CachedBeanData cacheBeanData, EntityBeanIntercept ebi, BeanProperty prop, PersistenceContext context) { if (cacheBeanData.isLoaded(prop.getName())) { if (!ebi.isLoadedProperty(prop.getPropertyIndex())) { Object value = cacheBeanData.getData(prop.getName()); - prop.setCacheDataValue(bean, value); + prop.setCacheDataValue(bean, value, context); } } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/cache/DefaultServerCache.java b/src/main/java/com/avaje/ebeaninternal/server/cache/DefaultServerCache.java index 9269616f0..d7db64a10 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/cache/DefaultServerCache.java +++ b/src/main/java/com/avaje/ebeaninternal/server/cache/DefaultServerCache.java @@ -107,15 +107,12 @@ public class DefaultServerCache implements ServerCache { return 0; } - @Override - public void init(EbeanServer server) { + public void periodicTrim(BackgroundExecutor executor) { EvictionRunnable trim = new EvictionRunnable(); // default to trimming the cache every 60 seconds long trimFreqSecs = (trimFrequency == 0) ? 60 : trimFrequency; - - BackgroundExecutor executor = server.getBackgroundExecutor(); executor.executePeriodically(trim, trimFreqSecs, TimeUnit.SECONDS); } @@ -176,33 +173,6 @@ public class DefaultServerCache implements ServerCache { } } - /** - * Return the options controlling the cache. - */ - @Override - public ServerCacheOptions getOptions() { - synchronized (monitor) { - ServerCacheOptions options = new ServerCacheOptions(); - options.setMaxIdleSecs(maxIdleSecs); - options.setMaxSize(maxSize); - options.setMaxSecsToLive(maxSecsToLive); - options.setTrimFrequency(trimFrequency); - return options; - } - } - - /** - * Set the options controlling the cache - */ - @Override - public void setOptions(ServerCacheOptions options) { - synchronized (monitor) { - maxIdleSecs = options.getMaxIdleSecs(); - maxSize = options.getMaxSize(); - maxSecsToLive = options.getMaxSecsToLive(); - } - } - /** * Return the name of the cache. */ diff --git a/src/main/java/com/avaje/ebeaninternal/server/cache/DefaultServerCacheFactory.java b/src/main/java/com/avaje/ebeaninternal/server/cache/DefaultServerCacheFactory.java index 62c22abbe..a17eb0b88 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/cache/DefaultServerCacheFactory.java +++ b/src/main/java/com/avaje/ebeaninternal/server/cache/DefaultServerCacheFactory.java @@ -1,6 +1,6 @@ package com.avaje.ebeaninternal.server.cache; -import com.avaje.ebean.EbeanServer; +import com.avaje.ebean.BackgroundExecutor; import com.avaje.ebean.cache.ServerCache; import com.avaje.ebean.cache.ServerCacheFactory; import com.avaje.ebean.cache.ServerCacheOptions; @@ -10,18 +10,30 @@ import com.avaje.ebean.cache.ServerCacheType; /** * Default implementation of ServerCacheFactory. */ -public class DefaultServerCacheFactory implements ServerCacheFactory { +class DefaultServerCacheFactory implements ServerCacheFactory { - private EbeanServer ebeanServer; + private final BackgroundExecutor executor; - public void init(EbeanServer ebeanServer) { - this.ebeanServer = ebeanServer; + /** + * Construct when l2 cache is disabled. + */ + public DefaultServerCacheFactory() { + this.executor = null; + } + + /** + * Construct with executor service. + */ + public DefaultServerCacheFactory(BackgroundExecutor executor) { + this.executor = executor; } public ServerCache createCache(ServerCacheType type, String cacheKey, ServerCacheOptions cacheOptions) { - ServerCache cache = new DefaultServerCache(cacheKey, cacheOptions); - cache.init(ebeanServer); + DefaultServerCache cache = new DefaultServerCache(cacheKey, cacheOptions); + if (executor != null) { + cache.periodicTrim(executor); + } return cache; } diff --git a/src/main/java/com/avaje/ebeaninternal/server/cache/DefaultServerCacheManager.java b/src/main/java/com/avaje/ebeaninternal/server/cache/DefaultServerCacheManager.java index 93865ac9e..f8abeb657 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/cache/DefaultServerCacheManager.java +++ b/src/main/java/com/avaje/ebeaninternal/server/cache/DefaultServerCacheManager.java @@ -1,12 +1,10 @@ package com.avaje.ebeaninternal.server.cache; -import com.avaje.ebean.EbeanServer; import com.avaje.ebean.cache.ServerCache; import com.avaje.ebean.cache.ServerCacheFactory; import com.avaje.ebean.cache.ServerCacheManager; import com.avaje.ebean.cache.ServerCacheOptions; import com.avaje.ebean.cache.ServerCacheType; -import com.avaje.ebeaninternal.api.SpiEbeanServer; /** @@ -22,15 +20,10 @@ public class DefaultServerCacheManager implements ServerCacheManager { private final DefaultCacheHolder collectionIdsCache; - private final ServerCacheFactory cacheFactory; - - private SpiEbeanServer ebeanServer; - /** * Create with a cache factory and default cache options. */ public DefaultServerCacheManager(ServerCacheFactory cacheFactory, ServerCacheOptions defaultBeanOptions, ServerCacheOptions defaultQueryOptions) { - this.cacheFactory = cacheFactory; this.beanCache = new DefaultCacheHolder(cacheFactory, defaultBeanOptions); this.queryCache = new DefaultCacheHolder(cacheFactory, defaultQueryOptions); this.naturalKeyCache = new DefaultCacheHolder(cacheFactory, defaultBeanOptions); @@ -44,18 +37,6 @@ public class DefaultServerCacheManager implements ServerCacheManager { this(new DefaultServerCacheFactory(), new ServerCacheOptions(), new ServerCacheOptions()); } - public void init(EbeanServer server) { - cacheFactory.init(server); - this.ebeanServer = (SpiEbeanServer) server; - } - - /** - * Set bean caching on or off for a given bean type. - */ - public void setCaching(Class beanType, boolean useCache) { - ebeanServer.getBeanDescriptor(beanType).setUseCache(useCache); - } - /** * Clear both the bean cache and the query cache for a * given bean type. diff --git a/src/main/java/com/avaje/ebeaninternal/server/cache/DefaultServerCachePlugin.java b/src/main/java/com/avaje/ebeaninternal/server/cache/DefaultServerCachePlugin.java new file mode 100644 index 000000000..9432056ac --- /dev/null +++ b/src/main/java/com/avaje/ebeaninternal/server/cache/DefaultServerCachePlugin.java @@ -0,0 +1,20 @@ +package com.avaje.ebeaninternal.server.cache; + +import com.avaje.ebean.BackgroundExecutor; +import com.avaje.ebean.cache.ServerCacheFactory; +import com.avaje.ebean.cache.ServerCachePlugin; +import com.avaje.ebean.config.ServerConfig; + +/** + * Default implementation of ServerCachePlugin. + */ +public class DefaultServerCachePlugin implements ServerCachePlugin { + + /** + * Creates the default ServerCacheFactory. + */ + @Override + public ServerCacheFactory create(ServerConfig config, BackgroundExecutor executor) { + return new DefaultServerCacheFactory(executor); + } +} diff --git a/src/main/java/com/avaje/ebeaninternal/server/core/CacheOptions.java b/src/main/java/com/avaje/ebeaninternal/server/core/CacheOptions.java index 0ca7641aa..89477900d 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/core/CacheOptions.java +++ b/src/main/java/com/avaje/ebeaninternal/server/core/CacheOptions.java @@ -1,111 +1,67 @@ package com.avaje.ebeaninternal.server.core; +import com.avaje.ebean.annotation.Cache; + /** * Options for controlling cache behaviour for a given type. */ public class CacheOptions { - private boolean useCache; - - private boolean readOnly; - - private String naturalKey; - - private int maxIdleSecs; - - private long maxSecsToLive; - /** - * Construct with options. + * Instance when no caching is used. */ - public CacheOptions() { + public static CacheOptions NO_CACHING = new CacheOptions(); + + private final boolean enableBeanCache; + private final boolean enableQueryCache; + private final boolean readOnly; + private final String naturalKey; + + /** + * Construct for no caching. + */ + private CacheOptions() { + enableBeanCache = false; + enableQueryCache = false; + readOnly = false; + naturalKey = null; } /** - * Return true if this should use a cache for lazy loading. + * Construct with cache annotation. */ - public boolean isUseCache() { - return useCache; + public CacheOptions(Cache cache, String naturalKey) { + enableBeanCache = cache.enableBeanCache(); + enableQueryCache = cache.enableQueryCache(); + readOnly = cache.readOnly(); + this.naturalKey = naturalKey; } /** - * Set whether to use the bean cache for the associated type. + * Return true if bean caching is enabled. */ - public void setUseCache(boolean useCache) { - this.useCache = useCache; + public boolean isEnableBeanCache() { + return enableBeanCache; } /** - * Return the readOnly default setting. + * Return true if query caching is enabled. + */ + public boolean isEnableQueryCache() { + return enableQueryCache; + } + + /** + * Return true if bean cache hits default to read only. */ public boolean isReadOnly() { return readOnly; } /** - * Set read Only default setting. - */ - public void setReadOnly(boolean readOnly) { - this.readOnly = readOnly; - } - - /** - * Return true if a natural key is set. - */ - public boolean isUseNaturalKeyCache() { - return naturalKey != null; - } - - /** - * Return the natural key property. + * Return the natural key property name. */ public String getNaturalKey() { return naturalKey; } - - /** - * Set the natural key property. - */ - public void setNaturalKey(String naturalKey) { - if (naturalKey != null && naturalKey.length() != 0) { - this.naturalKey = naturalKey.trim(); - } - } - - /** - * Return the max age of entries in seconds. - */ - public long getMaxSecsToLive() { - return maxSecsToLive; - } - - /** - * Set the max age of entries in seconds. - */ - public void setMaxSecsToLive(long maxSecsToLive) { - this.maxSecsToLive = maxSecsToLive; - } - - /** - * Set the max idle seconds. - */ - public void setMaxIdleSecs(int maxIdleSecs) { - this.maxIdleSecs = maxIdleSecs; - } - - /** - * Return the max idle seconds. - */ - public int getMaxIdleSecs() { - return maxIdleSecs; - } - - /** - * Return true if the entry exceeds the maxIdleSecs or maxSecsToLive. - */ - public boolean isTooOldInMillis(long ageMillis) { - long secs = ageMillis / 1000; - return (maxIdleSecs > 0 && secs > maxIdleSecs) || (maxSecsToLive > 0 && secs > maxSecsToLive); - } - } diff --git a/src/main/java/com/avaje/ebeaninternal/server/core/DefaultBeanLoader.java b/src/main/java/com/avaje/ebeaninternal/server/core/DefaultBeanLoader.java index a2b13a15d..ed319ff8a 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/core/DefaultBeanLoader.java +++ b/src/main/java/com/avaje/ebeaninternal/server/core/DefaultBeanLoader.java @@ -270,15 +270,15 @@ public class DefaultBeanLoader { boolean draft = desc.isDraftInstance(bean); if (embeddedOwnerIndex == -1) { - if (!draft && SpiQuery.Mode.LAZYLOAD_BEAN.equals(mode) && desc.isBeanCaching()) { - // lazy loading and the bean cache is active - if (desc.cacheBeanLoad(bean, ebi, id)) { - return; - } - } if (desc.lazyLoadMany(ebi)) { return; } + if (!draft && SpiQuery.Mode.LAZYLOAD_BEAN.equals(mode) && desc.isBeanCaching()) { + // lazy loading and the bean cache is active + if (desc.cacheBeanLoad(bean, ebi, id, pc)) { + return; + } + } } SpiQuery query = (SpiQuery) server.createQuery(desc.getBeanType()); diff --git a/src/main/java/com/avaje/ebeaninternal/server/core/DefaultContainer.java b/src/main/java/com/avaje/ebeaninternal/server/core/DefaultContainer.java index 4dc2fa465..d757568d2 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/core/DefaultContainer.java +++ b/src/main/java/com/avaje/ebeaninternal/server/core/DefaultContainer.java @@ -1,8 +1,10 @@ package com.avaje.ebeaninternal.server.core; +import com.avaje.ebean.BackgroundExecutor; import com.avaje.ebean.cache.ServerCacheFactory; import com.avaje.ebean.cache.ServerCacheManager; import com.avaje.ebean.cache.ServerCacheOptions; +import com.avaje.ebean.cache.ServerCachePlugin; import com.avaje.ebean.common.SpiContainer; import com.avaje.ebean.config.ContainerConfig; import com.avaje.ebean.config.PropertyMap; @@ -12,7 +14,7 @@ import com.avaje.ebean.config.dbplatform.DatabasePlatform; import com.avaje.ebean.dbmigration.DbOffline; import com.avaje.ebeaninternal.api.SpiBackgroundExecutor; import com.avaje.ebeaninternal.api.SpiEbeanServer; -import com.avaje.ebeaninternal.server.cache.DefaultServerCacheFactory; +import com.avaje.ebeaninternal.server.cache.DefaultServerCachePlugin; import com.avaje.ebeaninternal.server.cache.DefaultServerCacheManager; import com.avaje.ebeaninternal.server.cluster.ClusterManager; import com.avaje.ebeaninternal.server.lib.ShutdownManager; @@ -108,19 +110,15 @@ public class DefaultContainer implements SpiContainer { // inform the NamingConvention of the associated DatabasePlatform serverConfig.getNamingConvention().setDatabasePlatform(serverConfig.getDatabasePlatform()); - ServerCacheManager cacheManager = getCacheManager(online, serverConfig); + // executor and l2 caching service setup early (used during server construction) + SpiBackgroundExecutor executor = createBackgroundExecutor(serverConfig); + ServerCacheManager cacheManager = getCacheManager(online, serverConfig, executor); - SpiBackgroundExecutor bgExecutor = createBackgroundExecutor(serverConfig); - - XmlConfigLoader xmlConfigLoader = new XmlConfigLoader(null); - XmlConfig xmlConfig = xmlConfigLoader.load(); - - InternalConfiguration c = new InternalConfiguration(xmlConfig, clusterManager, cacheManager, bgExecutor, serverConfig, bootupClasses); + XmlConfig xmlConfig = new XmlConfigLoader(null).load(); + InternalConfiguration c = new InternalConfiguration(xmlConfig, clusterManager, cacheManager, executor, serverConfig, bootupClasses); DefaultServer server = new DefaultServer(c, cacheManager); - cacheManager.init(server); - // generate and run DDL if required // if there are any other tasks requiring action in their plugins, do them as well if (!DbOffline.isRunningMigration()) { @@ -147,7 +145,7 @@ public class DefaultContainer implements SpiContainer { /** * Create and return the CacheManager. */ - private ServerCacheManager getCacheManager(boolean online, ServerConfig serverConfig) { + private ServerCacheManager getCacheManager(boolean online, ServerConfig serverConfig, BackgroundExecutor executor) { if (!online || serverConfig.isDisableL2Cache()) { // use local only L2 cache implementation as placeholder @@ -171,21 +169,22 @@ public class DefaultContainer implements SpiContainer { queryOptions.setMaxIdleSecs(serverConfig.getQueryCacheMaxIdleTime()); queryOptions.setMaxSecsToLive(serverConfig.getQueryCacheMaxTimeToLive()); - ServerCacheFactory cacheFactory = serverConfig.getServerCacheFactory(); - if (cacheFactory == null) { - ServiceLoader cacheFactories = ServiceLoader.load(ServerCacheFactory.class); - Iterator iterator = cacheFactories.iterator(); + ServerCachePlugin plugin = serverConfig.getServerCachePlugin(); + if (plugin == null) { + ServiceLoader cacheFactories = ServiceLoader.load(ServerCachePlugin.class); + Iterator iterator = cacheFactories.iterator(); if (iterator.hasNext()) { // use the cacheFactory (via classpath service loader) - cacheFactory = iterator.next(); - logger.debug("using ServerCacheFactory {}", cacheFactory.getClass()); + plugin = iterator.next(); + logger.debug("using ServerCacheFactory {}", plugin.getClass()); } else { // use the built in default - cacheFactory = new DefaultServerCacheFactory(); + plugin = new DefaultServerCachePlugin(); } } - return new DefaultServerCacheManager(cacheFactory, beanOptions, queryOptions); + ServerCacheFactory factory = plugin.create(serverConfig, executor); + return new DefaultServerCacheManager(factory, beanOptions, queryOptions); } /** diff --git a/src/main/java/com/avaje/ebeaninternal/server/core/DefaultServer.java b/src/main/java/com/avaje/ebeaninternal/server/core/DefaultServer.java index f067a8350..b14c09953 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/core/DefaultServer.java +++ b/src/main/java/com/avaje/ebeaninternal/server/core/DefaultServer.java @@ -335,11 +335,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer { if (encryptKeyManager != null) { encryptKeyManager.initialise(); } - List> list = beanDescriptorManager.getBeanDescriptorList(); - for (int i = 0; i < list.size(); i++) { - list.get(i).cacheInitialise(); - } - } /** @@ -1026,7 +1021,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer { * Try to get the object out of the persistence context. */ @SuppressWarnings("unchecked") - private T findIdCheckPersistenceContextAndCache(Transaction transaction, SpiQuery query) { + private T findIdCheckPersistenceContextAndCache(Transaction transaction, SpiQuery query, Object id) { SpiTransaction t = (SpiTransaction) transaction; if (t == null) { @@ -1034,13 +1029,14 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer { } BeanDescriptor desc = query.getBeanDescriptor(); + id = desc.convertId(id); PersistenceContext pc = null; if (t != null && useTransactionPersistenceContext(query)) { // first look in the transaction scoped persistence context pc = t.getPersistenceContext(); if (pc != null) { - WithOption o = desc.contextGetWithOption(pc, query.getId()); + WithOption o = desc.contextGetWithOption(pc, id); if (o != null) { if (o.isDeleted()) { // Bean was previously deleted in the same transaction / persistence context @@ -1057,7 +1053,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer { } // Hit the L2 bean cache - return desc.cacheBeanGet(query, pc); + return desc.cacheBeanGet(id, query.isReadOnly(), pc); } /** @@ -1083,7 +1079,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer { if (SpiQuery.Mode.NORMAL.equals(spiQuery.getMode()) && !spiQuery.isLoadBeanCache()) { // See if we can skip doing the fetch completely by getting the bean from the // persistence context or the bean cache - T bean = findIdCheckPersistenceContextAndCache(t, spiQuery); + T bean = findIdCheckPersistenceContextAndCache(t, spiQuery, spiQuery.getId()); if (bean != null) { return bean; } @@ -1104,19 +1100,21 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer { public T findUnique(Query query, Transaction t) { - // actually a find by Id type of query... - // ... perhaps with joins and cache hints Object id = query.getId(); if (id != null) { + // actually a find by Id query return findId(query, t); } SpiQuery spiQuery = (SpiQuery) query; BeanDescriptor desc = spiQuery.getBeanDescriptor(); - T bean = desc.cacheNaturalKeyLookup(spiQuery, (SpiTransaction) t); - if (bean != null) { - return bean; + id = desc.cacheNaturalKeyIdLookup(spiQuery); + if (id != null) { + T bean = findIdCheckPersistenceContextAndCache(t, spiQuery, id); + if (bean != null) { + return bean; + } } // a query that is expected to return either 0 or 1 rows @@ -2025,16 +2023,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer { return beanDescriptorManager.getBeanDescriptorByClassName(beanClassName); } - @Override - public boolean initQueryCache(String key) { - BeanDescriptor desc = getBeanDescriptorById(key); - if (desc != null) { - desc.queryCacheInit(); - return true; - } - return false; - } - /** * Another server in the cluster sent this event so that we can inform local * BeanListeners of inserts updates and deletes that occurred remotely (on diff --git a/src/main/java/com/avaje/ebeaninternal/server/core/PersistRequestBean.java b/src/main/java/com/avaje/ebeaninternal/server/core/PersistRequestBean.java index 7b63e68cc..eb57cef1b 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/core/PersistRequestBean.java +++ b/src/main/java/com/avaje/ebeaninternal/server/core/PersistRequestBean.java @@ -548,7 +548,7 @@ public final class PersistRequestBean extends PersistRequest implements BeanP * Create and return a new reference bean matching this beans Id value. */ public T createReference() { - return beanDescriptor.createReference(Boolean.FALSE, getBeanId()); + return beanDescriptor.createReference(Boolean.FALSE, getBeanId(), null); } /** diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/AssocOneHelpRefInherit.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/AssocOneHelpRefInherit.java index ead82f1e6..6c2634f65 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/AssocOneHelpRefInherit.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/AssocOneHelpRefInherit.java @@ -46,7 +46,7 @@ class AssocOneHelpRefInherit extends AssocOneHelp { // check transaction context to see if it already exists PersistenceContext pc = ctx.getPersistenceContext(); - BeanDescriptor desc = rowInheritInfo.getBeanDescriptor(); + BeanDescriptor desc = rowInheritInfo.desc(); Object existing = desc.contextGet(pc, id); if (existing != null) { return existing; diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptor.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptor.java index 742e7088d..7d7234451 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptor.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptor.java @@ -39,7 +39,6 @@ import com.avaje.ebeaninternal.api.CQueryPlanKey; import com.avaje.ebeaninternal.api.LoadContext; import com.avaje.ebeaninternal.api.SpiEbeanServer; import com.avaje.ebeaninternal.api.SpiQuery; -import com.avaje.ebeaninternal.api.SpiTransaction; import com.avaje.ebeaninternal.api.SpiUpdatePlan; import com.avaje.ebeaninternal.api.TransactionEventTable.TableIUD; import com.avaje.ebeaninternal.server.cache.CacheChangeSet; @@ -723,7 +722,7 @@ public class BeanDescriptor implements MetaBeanInfo, BeanType { propertiesMany[i].initialisePostTarget(); } if (inheritInfo != null && !inheritInfo.isRoot()) { - docStoreAdapter = (DocStoreBeanAdapter)inheritInfo.getRoot().getBeanDescriptor().docStoreAdapter(); + docStoreAdapter = (DocStoreBeanAdapter)inheritInfo.getRoot().desc().docStoreAdapter(); } docMapping = docStoreAdapter.createDocMapping(); docStoreAdapter.registerPaths(); @@ -803,13 +802,6 @@ public class BeanDescriptor implements MetaBeanInfo, BeanType { return new BeanChange(getBaseTable(), id, changeType, values); } - /** - * Initialise the cache once the server has started. - */ - public void cacheInitialise() { - cacheHelp.initialise(); - } - public SqlUpdate deleteById(Object id, List idList, boolean softDelete) { if (id != null) { return deleteById(id, softDelete); @@ -996,7 +988,7 @@ public class BeanDescriptor implements MetaBeanInfo, BeanType { */ public BeanType root() { if (inheritInfo != null && !inheritInfo.isRoot()) { - return inheritInfo.getRoot().getBeanDescriptor(); + return inheritInfo.getRoot().desc(); } return this; } @@ -1046,13 +1038,6 @@ public class BeanDescriptor implements MetaBeanInfo, BeanType { return draftDirty; } - /** - * Set the bean caching on or off. - */ - public void setUseCache(boolean useCache) { - cacheHelp.setUseCache(useCache); - } - /** * Return true if there is currently bean caching for this type of bean. */ @@ -1082,10 +1067,6 @@ public class BeanDescriptor implements MetaBeanInfo, BeanType { return cacheHelp.isCacheNotify(); } - public void queryCacheInit() { - cacheHelp.queryCacheInit(); - } - /** * Clear the query cache. */ @@ -1153,22 +1134,22 @@ public class BeanDescriptor implements MetaBeanInfo, BeanType { /** * Load the embedded bean (taking into account inheritance). */ - public EntityBean cacheEmbeddedBeanLoad(CachedBeanData data) { - return cacheHelp.embeddedBeanLoad(data); + public EntityBean cacheEmbeddedBeanLoad(CachedBeanData data, PersistenceContext context) { + return cacheHelp.embeddedBeanLoad(data, context); } /** * Load the embedded bean as the root type. */ - EntityBean cacheEmbeddedBeanLoadDirect(CachedBeanData data) { - return cacheHelp.embeddedBeanLoadDirect(data); + EntityBean cacheEmbeddedBeanLoadDirect(CachedBeanData data, PersistenceContext context) { + return cacheHelp.embeddedBeanLoadDirect(data, context); } /** * Load the entity bean as the correct bean type. */ - EntityBean cacheBeanLoadDirect(Object id, Boolean readOnly, CachedBeanData data) { - return cacheHelp.loadBeanDirect(id, readOnly, data); + EntityBean cacheBeanLoadDirect(Object id, Boolean readOnly, CachedBeanData data, PersistenceContext context) { + return cacheHelp.loadBeanDirect(id, readOnly, data, context); } /** @@ -1195,8 +1176,8 @@ public class BeanDescriptor implements MetaBeanInfo, BeanType { /** * Return a bean from the bean cache (or null). */ - public T cacheBeanGet(SpiQuery query, PersistenceContext context) { - return cacheHelp.beanCacheGet(query, context); + public T cacheBeanGet(Object id, Boolean readOnly, PersistenceContext context) { + return cacheHelp.beanCacheGet(id, readOnly, context); } /** @@ -1209,24 +1190,24 @@ public class BeanDescriptor implements MetaBeanInfo, BeanType { /** * Returns true if it managed to populate/load the bean from the cache. */ - public boolean cacheBeanLoad(EntityBean bean, EntityBeanIntercept ebi, Object id) { - return cacheHelp.beanCacheLoad(bean, ebi, id); + public boolean cacheBeanLoad(EntityBean bean, EntityBeanIntercept ebi, Object id, PersistenceContext context) { + return cacheHelp.beanCacheLoad(bean, ebi, id, context); } /** * Returns true if it managed to populate/load the bean from the cache. */ - public boolean cacheBeanLoad(EntityBeanIntercept ebi) { + public boolean cacheBeanLoad(EntityBeanIntercept ebi, PersistenceContext context) { EntityBean bean = ebi.getOwner(); Object id = getId(bean); - return cacheBeanLoad(bean, ebi, id); + return cacheBeanLoad(bean, ebi, id, context); } /** * Try to hit the cache using the natural key. */ - public T cacheNaturalKeyLookup(SpiQuery query, SpiTransaction t) { - return cacheHelp.naturalKeyLookup(query, t); + public Object cacheNaturalKeyIdLookup(SpiQuery query) { + return cacheHelp.naturalKeyIdLookup(query); } public void cacheNaturalKeyPut(Object id, Object newKey) { @@ -1604,7 +1585,7 @@ public class BeanDescriptor implements MetaBeanInfo, BeanType { * Create a reference bean based on the id. */ @SuppressWarnings("unchecked") - public T createReference(Boolean readOnly, Object id) { + public T createReference(Boolean readOnly, Object id, PersistenceContext pc) { if (cacheSharableBeans && !Boolean.FALSE.equals(readOnly)) { CachedBeanData d = cacheHelp.beanCacheGetData(id); @@ -1620,7 +1601,7 @@ public class BeanDescriptor implements MetaBeanInfo, BeanType { } try { EntityBean eb = createEntityBean(); - convertSetId(id, eb); + id = convertSetId(id, eb); EntityBeanIntercept ebi = eb._ebean_getIntercept(); ebi.setBeanLoader(ebeanServer); @@ -1628,6 +1609,10 @@ public class BeanDescriptor implements MetaBeanInfo, BeanType { if (Boolean.TRUE == readOnly) { ebi.setReadOnly(true); } + if (pc != null) { + contextPut(pc, id, eb); + ebi.setPersistenceContext(pc); + } return (T) eb; @@ -1696,7 +1681,7 @@ public class BeanDescriptor implements MetaBeanInfo, BeanType { return unidirectional; } if (inheritInfo != null && !inheritInfo.isRoot()) { - return inheritInfo.getParent().getBeanDescriptor().getUnidirectional(); + return inheritInfo.getParent().desc().getUnidirectional(); } return null; } @@ -1792,11 +1777,7 @@ public class BeanDescriptor implements MetaBeanInfo, BeanType { * Create a reference bean and put it in the persistence context (and return it). */ public Object contextRef(PersistenceContext pc, Boolean readOnly, Object id) { - Object ref = createReference(readOnly, id); - if (pc != null) { - contextPut(pc, id, ref); - } - return ref; + return createReference(readOnly, id, pc); } /** @@ -1945,19 +1926,35 @@ public class BeanDescriptor implements MetaBeanInfo, BeanType { if (lazyLoadProperty == -1) { return false; } - String lazyLoadPropertyName = ebi.getProperty(lazyLoadProperty); - BeanProperty lazyLoadBeanProp = getBeanProperty(lazyLoadPropertyName); + if (inheritInfo != null) { + return descOf(ebi.getOwner().getClass()).lazyLoadMany(ebi, lazyLoadProperty); + } + return lazyLoadMany(ebi, lazyLoadProperty); + } + + /** + * Check for lazy loading of many property. + */ + private boolean lazyLoadMany(EntityBeanIntercept ebi, int lazyLoadProperty) { + + BeanProperty lazyLoadBeanProp = propertiesIndex[lazyLoadProperty]; if (lazyLoadBeanProp instanceof BeanPropertyAssocMany) { BeanPropertyAssocMany manyProp = (BeanPropertyAssocMany) lazyLoadBeanProp; manyProp.createReference(ebi.getOwner()); ebi.setLoadedLazy(); return true; } - return false; } + /** + * Return the correct BeanDescriptor based on the bean class type. + */ + BeanDescriptor descOf(Class type) { + return inheritInfo.readType(type).desc(); + } + /** * Return a Comparator for local sorting of lists. * @@ -2176,8 +2173,7 @@ public class BeanDescriptor implements MetaBeanInfo, BeanType { @Override @SuppressWarnings("unchecked") public T createBeanUsingDisc(Object discValue) { - InheritInfo type = inheritInfo.getType(discValue.toString()); - return (T)type.getBeanDescriptor().createBean(); + return (T) inheritInfo.getType(discValue.toString()).desc().createBean(); } @Override diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptorCacheHelp.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptorCacheHelp.java index 6f72ccb5e..cd71f3fd0 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptorCacheHelp.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptorCacheHelp.java @@ -7,7 +7,6 @@ import com.avaje.ebean.bean.PersistenceContext; import com.avaje.ebean.cache.ServerCache; import com.avaje.ebean.cache.ServerCacheManager; import com.avaje.ebeaninternal.api.SpiQuery; -import com.avaje.ebeaninternal.api.SpiTransaction; import com.avaje.ebeaninternal.api.TransactionEventTable.TableIUD; import com.avaje.ebeaninternal.server.cache.CacheChangeSet; import com.avaje.ebeaninternal.server.cache.CachedBeanData; @@ -57,9 +56,9 @@ final class BeanDescriptorCacheHelp { private final BeanPropertyAssocOne[] propertiesOneImported; private final String naturalKeyProperty; - private ServerCache beanCache; - private ServerCache naturalKeyCache; - private volatile ServerCache queryCache; + private final ServerCache beanCache; + private final ServerCache naturalKeyCache; + private final ServerCache queryCache; BeanDescriptorCacheHelp(BeanDescriptor desc, ServerCacheManager cacheManager, CacheOptions cacheOptions, boolean cacheSharableBeans, BeanPropertyAssocOne[] propertiesOneImported) { @@ -72,26 +71,23 @@ final class BeanDescriptorCacheHelp { this.cacheSharableBeans = cacheSharableBeans; this.propertiesOneImported = propertiesOneImported; this.naturalKeyProperty = cacheOptions.getNaturalKey(); - } - /** - * Initialise the cache once the server has started. - */ - public void initialise() { - if (cacheOptions.isUseNaturalKeyCache()) { - this.naturalKeyCache = cacheManager.getNaturalKeyCache(beanType); - } - if (cacheOptions.isUseCache()) { - this.beanCache = cacheManager.getBeanCache(beanType); - } - } - - public void setUseCache(boolean useCache) { - if (useCache) { - getBeanCache(); + if (!cacheOptions.isEnableQueryCache()) { + this.queryCache = null; } else { - beanCacheClear(); - beanCache = null; + this.queryCache = cacheManager.getQueryCache(beanType); + } + + if (cacheOptions.isEnableBeanCache()) { + this.beanCache = cacheManager.getBeanCache(beanType); + if (cacheOptions.getNaturalKey() != null) { + this.naturalKeyCache = cacheManager.getNaturalKeyCache(beanType); + } else { + this.naturalKeyCache = null; + } + } else { + this.beanCache = null; + this.naturalKeyCache = null; } } @@ -129,17 +125,6 @@ final class BeanDescriptorCacheHelp { return cacheOptions; } - /** - * Initialise the query cache if required - * (as some node in the cluster already has it). - */ - void queryCacheInit() { - if (queryCache == null) { - queryLog.debug(" init {}", cacheName); - queryCache = cacheManager.getQueryCache(beanType); - } - } - /** * Clear the query cache. */ @@ -167,18 +152,17 @@ final class BeanDescriptorCacheHelp { @SuppressWarnings("unchecked") BeanCollection queryCacheGet(Object id) { if (queryCache == null) { - return null; - } else { - BeanCollection list = (BeanCollection) queryCache.get(id); - if (queryLog.isDebugEnabled()) { - if (list == null) { - queryLog.debug(" GET {}({}) - cache miss", cacheName, id); - } else { - queryLog.debug(" GET {}({}) - hit", cacheName, id); - } - } - return list; + throw new IllegalStateException("No query cache enabled on " + desc + ". Need explicit @Cache(enableQueryCache=true)"); } + BeanCollection list = (BeanCollection) queryCache.get(id); + if (queryLog.isDebugEnabled()) { + if (list == null) { + queryLog.debug(" GET {}({}) - cache miss", cacheName, id); + } else { + queryLog.debug(" GET {}({}) - hit", cacheName, id); + } + } + return list; } /** @@ -186,7 +170,7 @@ final class BeanDescriptorCacheHelp { */ void queryCachePut(Object id, BeanCollection query) { if (queryCache == null) { - queryCache = cacheManager.getQueryCache(beanType); + throw new IllegalStateException("No query cache enabled on " + desc + ". Need explicit @Cache(enableQueryCache=true)"); } if (queryLog.isDebugEnabled()) { queryLog.debug(" PUT {}({})", cacheName, id); @@ -197,8 +181,8 @@ final class BeanDescriptorCacheHelp { void manyPropRemove(String propertyName, Object parentId) { ServerCache collectionIdsCache = cacheManager.getCollectionIdsCache(beanType, propertyName); - if (manyLog.isDebugEnabled()) { - manyLog.debug(" REMOVE {}({}).{}", cacheName, parentId, propertyName); + if (manyLog.isTraceEnabled()) { + manyLog.trace(" REMOVE {}({}).{}", cacheName, parentId, propertyName); } collectionIdsCache.remove(parentId); } @@ -248,12 +232,8 @@ final class BeanDescriptorCacheHelp { bc.checkEmptyLazyLoad(); for (int i = 0; i < idList.size(); i++) { Object id = idList.get(i); - Object refBean = targetDescriptor.createReference(readOnly, id); - EntityBeanIntercept refEbi = ((EntityBean) refBean)._ebean_getIntercept(); - + Object refBean = targetDescriptor.createReference(readOnly, id, persistenceContext); many.add(bc, (EntityBean) refBean); - targetDescriptor.contextPut(persistenceContext, id, refBean); - refEbi.setPersistenceContext(persistenceContext); } return true; } @@ -291,46 +271,26 @@ final class BeanDescriptorCacheHelp { /** * Find the bean using the natural key lookup if available. */ - T naturalKeyLookup(SpiQuery query, SpiTransaction t) { - + Object naturalKeyIdLookup(SpiQuery query) { + if (!isNaturalKeyCaching(query.isUseBeanCache())) { // no natural key caching for this query return null; } - + // check if it is a find by unique id (using the natural key) NaturalKeyBindParam keyBindParam = query.getNaturalKeyBindParam(); if (keyBindParam == null || !isNaturalKey(keyBindParam.getName())) { // query is not appropriate return null; } - + // try to lookup the id using the natural key Object id = naturalKeyCache.get(keyBindParam.getValue()); - if (natLog.isTraceEnabled()) { + if (natLog.isTraceEnabled() && id != null) { natLog.trace(" LOOKUP {}({}) - id:{}", cacheName, keyBindParam.getValue(), id); } - if (id == null) { - return null; - } - - // try looking up into the bean cache using the id - T cacheBean = beanCacheGetInternal(id, query.isReadOnly()); - if (cacheBean != null) { - setupContext(cacheBean, getPersistenceContext(t)); - } - return cacheBean; - } - - private PersistenceContext getPersistenceContext(SpiTransaction t) { - PersistenceContext context = null; - if (t == null) { - t = desc.getEbeanServer().getCurrentServerTransaction(); - } - if (t != null) { - context = t.getPersistenceContext(); - } - return context; + return id; } private boolean isNaturalKeyCaching(Boolean queryUseCache) { @@ -363,7 +323,7 @@ final class BeanDescriptorCacheHelp { */ private ServerCache getBeanCache() { if (beanCache == null) { - beanCache = cacheManager.getBeanCache(beanType); + throw new IllegalStateException("No bean cache enabled for " + desc + ". Add the @Cache annotation."); } return beanCache; } @@ -390,7 +350,7 @@ final class BeanDescriptorCacheHelp { void beanCachePut(EntityBean bean) { if (desc.inheritInfo != null) { - desc.inheritInfo.readType(bean.getClass()).getBeanDescriptor().cacheBeanPutDirect(bean); + desc.descOf(bean.getClass()).cacheBeanPutDirect(bean); } else { beanCachePutDirect(bean); } @@ -424,9 +384,8 @@ final class BeanDescriptorCacheHelp { return (CachedBeanData) getBeanCache().get(id); } - T beanCacheGet(SpiQuery query, PersistenceContext context) { - Object id = desc.convertId(query.getId()); - T bean = beanCacheGetInternal(id, query.isReadOnly()); + T beanCacheGet(Object id, Boolean readOnly, PersistenceContext context) { + T bean = beanCacheGetInternal(id, readOnly, context); if (bean != null) { setupContext(bean, context); } @@ -437,7 +396,7 @@ final class BeanDescriptorCacheHelp { * Return a bean from the bean cache. */ @SuppressWarnings("unchecked") - private T beanCacheGetInternal(Object id, Boolean readOnly) { + private T beanCacheGetInternal(Object id, Boolean readOnly, PersistenceContext context) { CachedBeanData data = (CachedBeanData) getBeanCache().get(id); if (data == null) { @@ -459,19 +418,19 @@ final class BeanDescriptorCacheHelp { } } - return (T)loadBean(id, readOnly, data); + return (T)loadBean(id, readOnly, data, context); } /** * Load the entity bean taking into account inheritance. */ - private EntityBean loadBean(Object id, Boolean readOnly, CachedBeanData data) { + private EntityBean loadBean(Object id, Boolean readOnly, CachedBeanData data, PersistenceContext context) { String discValue = data.getDiscValue(); if (discValue == null) { - return loadBeanDirect(id, readOnly, data); + return loadBeanDirect(id, readOnly, data, context); } else { - return rootDescriptor(discValue).cacheBeanLoadDirect(id, readOnly, data); + return rootDescriptor(discValue).cacheBeanLoadDirect(id, readOnly, data, context); } } @@ -479,24 +438,32 @@ final class BeanDescriptorCacheHelp { * Return the root BeanDescriptor for inheritance. */ private BeanDescriptor rootDescriptor(String discValue) { - InheritInfo inheritInfo = desc.inheritInfo.readType(discValue); - return inheritInfo.getBeanDescriptor(); + return desc.inheritInfo.readType(discValue).desc(); } /** * Load the entity bean from cache data given this is the root bean type. */ - EntityBean loadBeanDirect(Object id, Boolean readOnly, CachedBeanData data) { + EntityBean loadBeanDirect(Object id, Boolean readOnly, CachedBeanData data, PersistenceContext context) { + + if (context == null) { + context = new DefaultPersistenceContext(); + } EntityBean bean = desc.createEntityBean(); - desc.convertSetId(id, bean); - CachedBeanDataToBean.load(desc, bean, data); + id = desc.convertSetId(id, bean); + CachedBeanDataToBean.load(desc, bean, data, context); EntityBeanIntercept ebi = bean._ebean_getIntercept(); + + // Not using a loadContext for beans coming out of L2 cache + // so that means no batch lazy loading for these beans ebi.setBeanLoader(desc.getEbeanServer()); if (Boolean.TRUE.equals(readOnly)) { ebi.setReadOnly(true); } + ebi.setPersistenceContext(context); + desc.contextPut(context, id, bean); if (beanLog.isTraceEnabled()) { beanLog.trace(" GET {}({}) - hit", cacheName, id); @@ -510,22 +477,22 @@ final class BeanDescriptorCacheHelp { /** * Load the embedded bean checking for inheritance. */ - EntityBean embeddedBeanLoad(CachedBeanData data) { + EntityBean embeddedBeanLoad(CachedBeanData data, PersistenceContext context) { String discValue = data.getDiscValue(); if (discValue == null) { - return embeddedBeanLoadDirect(data); + return embeddedBeanLoadDirect(data, context); } else { - return rootDescriptor(discValue).cacheEmbeddedBeanLoadDirect(data); + return rootDescriptor(discValue).cacheEmbeddedBeanLoadDirect(data, context); } } /** * Load the embedded bean given this is the bean type. */ - EntityBean embeddedBeanLoadDirect(CachedBeanData data) { + EntityBean embeddedBeanLoadDirect(CachedBeanData data, PersistenceContext context) { EntityBean bean = desc.createEntityBean(); - CachedBeanDataToBean.load(desc, bean, data); + CachedBeanDataToBean.load(desc, bean, data, context); return bean; } @@ -547,7 +514,7 @@ final class BeanDescriptorCacheHelp { /** * Returns true if it managed to populate/load the bean from the cache. */ - boolean beanCacheLoad(EntityBean bean, EntityBeanIntercept ebi, Object id) { + boolean beanCacheLoad(EntityBean bean, EntityBeanIntercept ebi, Object id, PersistenceContext context) { CachedBeanData cacheData = (CachedBeanData) getBeanCache().get(id); if (cacheData == null) { @@ -559,12 +526,12 @@ final class BeanDescriptorCacheHelp { int lazyLoadProperty = ebi.getLazyLoadPropertyIndex(); if (lazyLoadProperty > -1 && !cacheData.isLoaded(ebi.getLazyLoadProperty())) { if (beanLog.isTraceEnabled()) { - beanLog.trace(" LOAD {}({}) - cache miss on property", cacheName, id); + beanLog.trace(" LOAD {}({}) - cache miss on property({})", cacheName, id, ebi.getLazyLoadProperty()); } return false; } - CachedBeanDataToBean.load(desc, bean, cacheData); + CachedBeanDataToBean.load(desc, bean, cacheData, context); if (beanLog.isDebugEnabled()) { beanLog.debug(" LOAD {}({}) - hit", cacheName, id); } @@ -650,10 +617,6 @@ final class BeanDescriptorCacheHelp { } } - private boolean isCachedDataTooOld(CachedBeanData existingData) { - return cacheOptions.isTooOldInMillis(System.currentTimeMillis() - existingData.getWhenCreated()); - } - /** * Invalidate parts of cache due to SqlUpdate or external modification etc. */ @@ -680,28 +643,21 @@ final class BeanDescriptorCacheHelp { ServerCache cache = getBeanCache(); CachedBeanData existingData = (CachedBeanData) cache.get(id); if (existingData != null) { - if (isCachedDataTooOld(existingData)) { + long currentVersion = existingData.getVersion(); + if (version > 0 && version < currentVersion) { if (beanLog.isDebugEnabled()) { - beanLog.debug(" REMOVE {}({}) - entry too old", cacheName, id); + beanLog.debug(" REMOVE {}({}) - version conflict old:{} new:{}", cacheName, id, currentVersion, version); } cache.remove(id); } else { - long currentVersion = existingData.getVersion(); - if (version > 0 && version < currentVersion) { - if (beanLog.isDebugEnabled()) { - beanLog.debug(" REMOVE {}({}) - version conflict old:{} new:{}", cacheName, id, currentVersion, version); - } - cache.remove(id); - } else { - if (version == 0) { - version = currentVersion; - } - CachedBeanData newData = existingData.update(changes, version); - if (beanLog.isDebugEnabled()) { - beanLog.debug(" UPDATE {}({}) changes:{}", cacheName, id, changes); - } - cache.put(id, newData); + if (version == 0) { + version = currentVersion; } + CachedBeanData newData = existingData.update(changes, version); + if (beanLog.isDebugEnabled()) { + beanLog.debug(" UPDATE {}({}) changes:{}", cacheName, id, changes); + } + cache.put(id, newData); } if (updateNaturalKey) { diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptorJsonHelp.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptorJsonHelp.java index a189241a1..cf220a3c8 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptorJsonHelp.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptorJsonHelp.java @@ -37,8 +37,7 @@ public class BeanDescriptorJsonHelp { String discColumn = localInheritInfo.getDiscriminatorColumn(); writeJson.gen().writeStringField(discColumn, discValue); - BeanDescriptor localDescriptor = localInheritInfo.getBeanDescriptor(); - localDescriptor.jsonWriteProperties(writeJson, bean); + localInheritInfo.desc().jsonWriteProperties(writeJson, bean); } writeJson.writeEndObject(); @@ -54,13 +53,9 @@ public class BeanDescriptorJsonHelp { if (inheritInfo == null) { jsonWriteDirtyProperties(writeJson, bean, dirtyProps); - } else { - InheritInfo localInheritInfo = inheritInfo.readType(bean.getClass()); - BeanDescriptor localDescriptor = localInheritInfo.getBeanDescriptor(); - localDescriptor.jsonWriteDirtyProperties(writeJson, bean, dirtyProps); + desc.descOf(bean.getClass()).jsonWriteDirtyProperties(writeJson, bean, dirtyProps); } - } protected void jsonWriteDirtyProperties(WriteJson writeJson, EntityBean bean, boolean[] dirtyProps) throws IOException { @@ -120,11 +115,7 @@ public class BeanDescriptorJsonHelp { } String discValue = parser.nextTextValue(); - - // determine the sub type for this particular json object - InheritInfo localInheritInfo = inheritInfo.readType(discValue); - BeanDescriptor localDescriptor = localInheritInfo.getBeanDescriptor(); - return (T) localDescriptor.jsonReadObject(jsonRead, path); + return (T) inheritInfo.readType(discValue).desc().jsonReadObject(jsonRead, path); } protected T jsonReadObject(ReadJson readJson, String path) throws IOException { diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanProperty.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanProperty.java index d097ddc97..06091ed55 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanProperty.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanProperty.java @@ -2,6 +2,7 @@ package com.avaje.ebeaninternal.server.deploy; import com.avaje.ebean.ValuePair; import com.avaje.ebean.bean.EntityBean; +import com.avaje.ebean.bean.PersistenceContext; import com.avaje.ebean.config.EncryptKey; import com.avaje.ebean.config.dbplatform.DbEncryptFunction; import com.avaje.ebean.config.dbplatform.DbType; @@ -764,7 +765,7 @@ public class BeanProperty implements ElPropertyValue, Property { * This uses parse() as per the comment in getCacheDataValue(). *

*/ - public void setCacheDataValue(EntityBean bean, Object cacheData) { + public void setCacheDataValue(EntityBean bean, Object cacheData, PersistenceContext context) { if (cacheData instanceof String) { // parse back from string to support optimisation of java object serialisation cacheData = scalarType.parse((String)cacheData); diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssocMany.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssocMany.java index fc364ac21..9fd52d7c3 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssocMany.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssocMany.java @@ -1022,7 +1022,7 @@ public class BeanPropertyAssocMany extends BeanPropertyAssoc { if (isManyToMany()) { if (liveBean == null) { // add new relationship (Map not allowed here) - liveVal.addBean(targetDescriptor.createReference(Boolean.FALSE, id)); + liveVal.addBean(targetDescriptor.createReference(Boolean.FALSE, id, null)); } } else { diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssocOne.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssocOne.java index d299cb57e..d79ddef60 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssocOne.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssocOne.java @@ -6,6 +6,7 @@ import com.avaje.ebean.SqlUpdate; import com.avaje.ebean.Transaction; import com.avaje.ebean.ValuePair; import com.avaje.ebean.bean.EntityBean; +import com.avaje.ebean.bean.PersistenceContext; import com.avaje.ebeaninternal.server.cache.CacheChangeSet; import com.avaje.ebeaninternal.server.cache.CachedBeanData; import com.avaje.ebeaninternal.server.core.DefaultSqlUpdate; @@ -399,17 +400,22 @@ public class BeanPropertyAssocOne extends BeanPropertyAssoc { } @Override - public void setCacheDataValue(EntityBean bean, Object cacheData) { + public void setCacheDataValue(EntityBean bean, Object cacheData, PersistenceContext context) { if (cacheData == null) { setValue(bean, null); } else { if (embedded) { - setValue(bean, targetDescriptor.cacheEmbeddedBeanLoad((CachedBeanData) cacheData)); + setValue(bean, targetDescriptor.cacheEmbeddedBeanLoad((CachedBeanData) cacheData, context)); } else { if (cacheData instanceof String) { cacheData = targetDescriptor.getIdProperty().scalarType.parse((String)cacheData); } - setValue(bean, targetDescriptor.createReference(Boolean.FALSE, cacheData)); + // cacheData is the id value, maybe already in persistence context + Object assocBean = targetDescriptor.contextGet(context, cacheData); + if (assocBean == null) { + assocBean = targetDescriptor.createReference(Boolean.FALSE, cacheData, context); + } + setValue(bean, assocBean); } } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/InheritInfo.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/InheritInfo.java index 28ba06a7d..d8433bad6 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/InheritInfo.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/InheritInfo.java @@ -141,7 +141,7 @@ public class InheritInfo { /** * Return the associated BeanDescriptor for this node. */ - public BeanDescriptor getBeanDescriptor() { + public BeanDescriptor desc() { return descriptor; } @@ -161,10 +161,8 @@ public class InheritInfo { for (int i = 0, x = children.size(); i < x; i++) { InheritInfo childInfo = children.get(i); - // recursively search this child bean descriptor - prop = childInfo.getBeanDescriptor().findBeanProperty(propertyName); - + prop = childInfo.desc().findBeanProperty(propertyName); if (prop != null) { return prop; } diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/meta/DeployBeanDescriptor.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/meta/DeployBeanDescriptor.java index fd1e69f85..ffc011528 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/meta/DeployBeanDescriptor.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/meta/DeployBeanDescriptor.java @@ -1,5 +1,6 @@ package com.avaje.ebeaninternal.server.deploy.meta; +import com.avaje.ebean.annotation.Cache; import com.avaje.ebeaninternal.api.ConcurrencyMode; import com.avaje.ebean.annotation.DocStore; import com.avaje.ebean.annotation.DocStoreMode; @@ -153,7 +154,7 @@ public class DeployBeanDescriptor { private final List queryAdapters = new ArrayList(); private final List postLoaders = new ArrayList(); - private final CacheOptions cacheOptions = new CacheOptions(); + private CacheOptions cacheOptions = CacheOptions.NO_CACHING; /** * If set overrides the find implementation. Server side only. @@ -442,6 +443,24 @@ public class DeployBeanDescriptor { this.inheritInfo = inheritInfo; } + /** + * Enable L2 bean and query caching based on Cache annotation. + */ + public void setCache(Cache cache) { + + String naturalKey = null; + if (cache.naturalKey().length() > 0) { + // find the property and mark as natural key property + String propName = cache.naturalKey().trim(); + DeployBeanProperty beanProperty = getBeanProperty(propName); + if (beanProperty != null) { + beanProperty.setNaturalKey(); + naturalKey = propName; + } + } + this.cacheOptions = new CacheOptions(cache, naturalKey); + } + /** * Return the cache options. */ diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/parse/AnnotationClass.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/parse/AnnotationClass.java index d1165812d..424c2b39f 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/parse/AnnotationClass.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/parse/AnnotationClass.java @@ -1,7 +1,6 @@ package com.avaje.ebeaninternal.server.deploy.parse; -import com.avaje.ebean.annotation.CacheStrategy; -import com.avaje.ebean.annotation.CacheBeanTuning; +import com.avaje.ebean.annotation.Cache; import com.avaje.ebean.annotation.DbComment; import com.avaje.ebean.annotation.DocStore; import com.avaje.ebean.annotation.Draftable; @@ -14,7 +13,6 @@ import com.avaje.ebean.annotation.ReadAudit; import com.avaje.ebean.annotation.UpdateMode; import com.avaje.ebean.annotation.View; import com.avaje.ebean.config.TableName; -import com.avaje.ebeaninternal.server.core.CacheOptions; import com.avaje.ebeaninternal.server.deploy.BeanDescriptor.EntityType; import com.avaje.ebeaninternal.server.deploy.CompoundUniqueConstraint; import com.avaje.ebeaninternal.server.deploy.DeployNamedQuery; @@ -202,34 +200,9 @@ public class AnnotationClass extends AnnotationParser { readNamedUpdate(namedUpdate); } - CacheStrategy cacheStrategy = cls.getAnnotation(CacheStrategy.class); - CacheBeanTuning cacheBeanTuning = cls.getAnnotation(CacheBeanTuning.class); - if (cacheStrategy != null || cacheBeanTuning != null) { - readCacheStrategy(cacheStrategy, cacheBeanTuning); - } - } - - private void readCacheStrategy(CacheStrategy cacheStrategy, CacheBeanTuning cacheBeanTuning) { - - if (disableL2Cache) { - return; - } - CacheOptions cacheOptions = descriptor.getCacheOptions(); - if (cacheBeanTuning != null) { - cacheOptions.setMaxSecsToLive(cacheBeanTuning.maxSecsToLive()); - cacheOptions.setMaxIdleSecs(cacheBeanTuning.maxIdleSecs()); - } - if (cacheStrategy != null) { - cacheOptions.setUseCache(cacheStrategy.useBeanCache()); - cacheOptions.setReadOnly(cacheStrategy.readOnly()); - if (cacheStrategy.naturalKey().length() > 0) { - String propName = cacheStrategy.naturalKey().trim(); - DeployBeanProperty beanProperty = descriptor.getBeanProperty(propName); - if (beanProperty != null) { - beanProperty.setNaturalKey(); - cacheOptions.setNaturalKey(propName); - } - } + Cache cache = cls.getAnnotation(Cache.class); + if (cache != null && !disableL2Cache) { + descriptor.setCache(cache); } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/loadcontext/DLoadBeanContext.java b/src/main/java/com/avaje/ebeaninternal/server/loadcontext/DLoadBeanContext.java index 575a1fc02..fe4af3aae 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/loadcontext/DLoadBeanContext.java +++ b/src/main/java/com/avaje/ebeaninternal/server/loadcontext/DLoadBeanContext.java @@ -175,7 +175,7 @@ public class DLoadBeanContext extends DLoadBaseContext implements LoadBeanContex return; } - if (context.hitCache && context.desc.cacheBeanLoad(ebi)) { + if (context.hitCache && context.desc.cacheBeanLoad(ebi, persistenceContext)) { // successfully hit the L2 cache so don't invoke DB lazy loading list.remove(ebi); return; @@ -185,7 +185,7 @@ public class DLoadBeanContext extends DLoadBaseContext implements LoadBeanContex // check each of the beans in the batch to see if they are in the L2 cache. Iterator iterator = list.iterator(); while (iterator.hasNext()) { - if (context.desc.cacheBeanLoad(iterator.next())) { + if (context.desc.cacheBeanLoad(iterator.next(), persistenceContext)) { iterator.remove(); } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/persist/DefaultPersister.java b/src/main/java/com/avaje/ebeaninternal/server/persist/DefaultPersister.java index ff2cd19c4..9bf0a2793 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/persist/DefaultPersister.java +++ b/src/main/java/com/avaje/ebeaninternal/server/persist/DefaultPersister.java @@ -1352,7 +1352,7 @@ public final class DefaultPersister implements Persister { // convert into a list of reference objects and perform delete by object List refList = new ArrayList(childIds.size()); for (Object id : childIds) { - refList.add(targetDesc.createReference(null, id)); + refList.add(targetDesc.createReference(null, id, null)); } deleteList(refList, t, softDelete); diff --git a/src/main/java/com/avaje/ebeaninternal/server/query/SqlTreeNodeBean.java b/src/main/java/com/avaje/ebeaninternal/server/query/SqlTreeNodeBean.java index 0466085ee..b200378cd 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/query/SqlTreeNodeBean.java +++ b/src/main/java/com/avaje/ebeaninternal/server/query/SqlTreeNodeBean.java @@ -218,7 +218,7 @@ public class SqlTreeNodeBean implements SqlTreeNode { localBean = localInfo.createEntityBean(); localType = localInfo.getType(); localIdBinder = localInfo.getIdBinder(); - localDesc = localInfo.getBeanDescriptor(); + localDesc = localInfo.desc(); } } else { diff --git a/src/test/java/com/avaje/ebeaninternal/server/cache/CacheBeanDataTest.java b/src/test/java/com/avaje/ebeaninternal/server/cache/CacheBeanDataTest.java index 86af25558..bfb172161 100644 --- a/src/test/java/com/avaje/ebeaninternal/server/cache/CacheBeanDataTest.java +++ b/src/test/java/com/avaje/ebeaninternal/server/cache/CacheBeanDataTest.java @@ -2,9 +2,11 @@ package com.avaje.ebeaninternal.server.cache; import com.avaje.ebean.BaseTestCase; import com.avaje.ebean.bean.EntityBean; +import com.avaje.ebean.bean.PersistenceContext; import com.avaje.ebeaninternal.api.SpiEbeanServer; import com.avaje.ebeaninternal.server.deploy.BeanDescriptor; import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocOne; +import com.avaje.ebeaninternal.server.transaction.DefaultPersistenceContext; import com.avaje.tests.model.basic.Address; import com.avaje.tests.model.basic.Country; import com.avaje.tests.model.basic.Customer; @@ -50,7 +52,7 @@ public class CacheBeanDataTest extends BaseTestCase { Customer newCustomer = new Customer(); newCustomer.setId(c.getId()); - CachedBeanDataToBean.load(desc, (EntityBean) newCustomer, cacheData); + CachedBeanDataToBean.load(desc, (EntityBean) newCustomer, cacheData, new DefaultPersistenceContext()); assertEquals(c.getId(), newCustomer.getId()); assertEquals(c.getName(), newCustomer.getName()); @@ -91,9 +93,11 @@ public class CacheBeanDataTest extends BaseTestCase { CachedBeanData addressCacheData = (CachedBeanData) addressBeanProperty.getCacheDataValue((EntityBean) person); + PersistenceContext context = new DefaultPersistenceContext(); + EPerson newPersonCheck = new EPerson(); newPersonCheck.setId(98989L); - addressBeanProperty.setCacheDataValue((EntityBean) newPersonCheck, addressCacheData); + addressBeanProperty.setCacheDataValue((EntityBean) newPersonCheck, addressCacheData, context); EAddress newAddress = newPersonCheck.getAddress(); assertEquals(address.getStreet(), newAddress.getStreet()); @@ -105,7 +109,7 @@ public class CacheBeanDataTest extends BaseTestCase { assertNotNull(cacheData); - EPerson newPerson = (EPerson)desc.cacheEmbeddedBeanLoad(cacheData); + EPerson newPerson = (EPerson)desc.cacheEmbeddedBeanLoad(cacheData, context); assertNotNull(newPerson.getId()); assertNotNull(newPerson.getName()); diff --git a/src/test/java/com/avaje/ebeaninternal/server/cache/CachedBeanDataFromBeanTest.java b/src/test/java/com/avaje/ebeaninternal/server/cache/CachedBeanDataFromBeanTest.java index fe4282482..1bb294fc5 100644 --- a/src/test/java/com/avaje/ebeaninternal/server/cache/CachedBeanDataFromBeanTest.java +++ b/src/test/java/com/avaje/ebeaninternal/server/cache/CachedBeanDataFromBeanTest.java @@ -4,6 +4,7 @@ import com.avaje.ebean.BaseTestCase; import com.avaje.ebean.bean.EntityBean; import com.avaje.ebeaninternal.api.SpiEbeanServer; import com.avaje.ebeaninternal.server.deploy.BeanDescriptor; +import com.avaje.ebeaninternal.server.transaction.DefaultPersistenceContext; import com.avaje.tests.model.basic.Address; import com.avaje.tests.model.basic.Car; import com.avaje.tests.model.basic.Customer; @@ -51,7 +52,7 @@ public class CachedBeanDataFromBeanTest extends BaseTestCase { Car newCar = new Car(); EntityBean entityBean = (EntityBean)newCar; - CachedBeanDataToBean.load(carDesc, entityBean, cacheData); + CachedBeanDataToBean.load(carDesc, entityBean, cacheData, new DefaultPersistenceContext()); assertEquals(newCar.getId(), car.getId()); assertEquals(newCar.getDriver(), car.getDriver()); diff --git a/src/test/java/com/avaje/ebeaninternal/server/cache/CachedBeanDataSerializeTest.java b/src/test/java/com/avaje/ebeaninternal/server/cache/CachedBeanDataSerializeTest.java index 151824317..9d8907573 100644 --- a/src/test/java/com/avaje/ebeaninternal/server/cache/CachedBeanDataSerializeTest.java +++ b/src/test/java/com/avaje/ebeaninternal/server/cache/CachedBeanDataSerializeTest.java @@ -4,6 +4,7 @@ import com.avaje.ebean.BaseTestCase; import com.avaje.ebean.Ebean; import com.avaje.ebean.bean.EntityBean; import com.avaje.ebeaninternal.server.deploy.BeanDescriptor; +import com.avaje.ebeaninternal.server.transaction.DefaultPersistenceContext; import com.avaje.tests.model.basic.Customer; import com.avaje.tests.model.basic.ResetBasicData; import com.avaje.tests.model.basic.TBytesOnly; @@ -82,7 +83,7 @@ public class CachedBeanDataSerializeTest extends BaseTestCase { assertEquals(read.getData(), extract.getData()); Customer loadCustomer = new Customer(); - CachedBeanDataToBean.load(desc, (EntityBean)loadCustomer, read); + CachedBeanDataToBean.load(desc, (EntityBean)loadCustomer, read, new DefaultPersistenceContext()); assertEquals(loadCustomer.getVersion(), customer.getVersion()); assertEquals(loadCustomer.getId(), customer.getId()); @@ -113,7 +114,7 @@ public class CachedBeanDataSerializeTest extends BaseTestCase { assertTrue(Arrays.equals(bean.getContent(), extraContent)); TBytesOnly loadBean= new TBytesOnly(); - CachedBeanDataToBean.load(desc, (EntityBean)loadBean, read); + CachedBeanDataToBean.load(desc, (EntityBean)loadBean, read, new DefaultPersistenceContext()); assertEquals(loadBean.getId(), bean.getId()); assertTrue(Arrays.equals(loadBean.getContent(), bean.getContent())); diff --git a/src/test/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptorTest.java b/src/test/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptorTest.java index 1be4b9100..eda9a52d4 100644 --- a/src/test/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptorTest.java +++ b/src/test/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptorTest.java @@ -18,7 +18,7 @@ public class BeanDescriptorTest extends BaseTestCase { @Test public void createReference() { - Customer bean = customerDesc.createReference(null, 42); + Customer bean = customerDesc.createReference(null, 42, null); assertThat(bean.getId()).isEqualTo(42); assertThat(server().getBeanState(bean).isReadOnly()).isFalse(); } @@ -26,14 +26,14 @@ public class BeanDescriptorTest extends BaseTestCase { @Test public void createReference_whenReadOnly() { - Customer bean = customerDesc.createReference(Boolean.TRUE, 42); + Customer bean = customerDesc.createReference(Boolean.TRUE, 42, null); assertThat(server().getBeanState(bean).isReadOnly()).isTrue(); } @Test public void createReference_whenNotReadOnly() { - Customer bean = customerDesc.createReference(Boolean.FALSE, 42); + Customer bean = customerDesc.createReference(Boolean.FALSE, 42, null); assertThat(server().getBeanState(bean).isReadOnly()).isFalse(); } diff --git a/src/test/java/com/avaje/tests/autofetch/TunedQueryInfoTest.java b/src/test/java/com/avaje/tests/autofetch/TunedQueryInfoTest.java index 2d0cc5fcb..4ca564a39 100644 --- a/src/test/java/com/avaje/tests/autofetch/TunedQueryInfoTest.java +++ b/src/test/java/com/avaje/tests/autofetch/TunedQueryInfoTest.java @@ -32,7 +32,6 @@ public class TunedQueryInfoTest extends BaseTestCase { ServerCacheManager serverCacheManager = Ebean.getServer(null).getServerCacheManager(); serverCacheManager.clearAll(); - serverCacheManager.setCaching(Order.class, false); } @Test diff --git a/src/test/java/com/avaje/tests/basic/TestManyLazyLoad.java b/src/test/java/com/avaje/tests/basic/TestManyLazyLoad.java index 3849706f5..decb1c4a7 100644 --- a/src/test/java/com/avaje/tests/basic/TestManyLazyLoad.java +++ b/src/test/java/com/avaje/tests/basic/TestManyLazyLoad.java @@ -1,61 +1,66 @@ package com.avaje.tests.basic; -import java.sql.Date; -import java.util.List; - -import org.junit.Assert; -import org.junit.Test; - import com.avaje.ebean.BaseTestCase; import com.avaje.ebean.Ebean; import com.avaje.tests.model.basic.Order; import com.avaje.tests.model.basic.OrderDetail; import com.avaje.tests.model.basic.ResetBasicData; +import org.junit.Test; + +import java.sql.Date; +import java.util.List; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; public class TestManyLazyLoad extends BaseTestCase { - @Test - public void testLazyLoadRef() { - - ResetBasicData.reset(); - - List list = Ebean.find(Order.class).order().asc("id").findList(); - Assert.assertTrue(list.size()+" > 0", list.size() > 0); - - // just use the first one - Order order = list.get(0); - - // get it as a reference - Order order1 = Ebean.getReference(Order.class, order.getId()); - Assert.assertNotNull(order1); - - Date orderDate = order1.getOrderDate(); - Assert.assertNotNull(orderDate); - - List details = order1.getDetails(); - - // lazy load the details - int sz = details.size(); - Assert.assertTrue(sz+" > 0", sz > 0); - - Order o = details.get(0).getOrder(); - Assert.assertTrue("same instance", o == order1); - + @Test + public void testLazyLoadRef() throws InterruptedException { - // change order... list before a scalar property - Order order2 = Ebean.getReference(Order.class, order.getId()); - Assert.assertNotNull(order2); - - List details2 = order2.getDetails(); - - // lazy load the details - int sz2 = details2.size(); - Assert.assertTrue(sz2+" > 0", sz2 > 0); - - Order o2 = details2.get(0).getOrder(); - Assert.assertTrue("same instance", o2 == order2); + ResetBasicData.reset(); + + awaitL2Cache(); + + List list = Ebean.find(Order.class).order().asc("id").findList(); + assertTrue(list.size() + " > 0", list.size() > 0); + + // just use the first one + Order order = list.get(0); + + // get it as a reference + Order order1 = Ebean.getReference(Order.class, order.getId()); + assertNotNull(order1); + + Date orderDate = order1.getOrderDate(); + assertNotNull(orderDate); + + List details = order1.getDetails(); + + // lazy load the details + int sz = details.size(); + assertTrue(sz + " > 0", sz > 0); + + OrderDetail orderDetail = details.get(0); + Order o = orderDetail.getOrder(); + assertSame(o, order1); + + // load detail into cache + Ebean.find(OrderDetail.class, orderDetail.getId()); + + // change order... list before a scalar property + Order order2 = Ebean.getReference(Order.class, order.getId()); + assertNotNull(order2); + + List details2 = order2.getDetails(); + + // lazy load the details + int sz2 = details2.size(); + assertTrue(sz2 + " > 0", sz2 > 0); + + Order o2 = details2.get(0).getOrder(); + assertSame(o2, order2); + } - - } - } diff --git a/src/test/java/com/avaje/tests/basic/TestQueryWithCache.java b/src/test/java/com/avaje/tests/basic/TestQueryWithCache.java index 51251cb29..d4ec4a358 100644 --- a/src/test/java/com/avaje/tests/basic/TestQueryWithCache.java +++ b/src/test/java/com/avaje/tests/basic/TestQueryWithCache.java @@ -85,7 +85,6 @@ public class TestQueryWithCache extends BaseTestCase { CacheOptions cacheOptions = beanDescriptor.getCacheOptions(); Assert.assertNotNull(cacheOptions); - Assert.assertTrue(cacheOptions.isUseCache()); Assert.assertTrue(cacheOptions.isReadOnly()); Assert.assertTrue(beanDescriptor.isCacheSharableBeans()); diff --git a/src/test/java/com/avaje/tests/batchload/TestBatchLazyWithCacheHits.java b/src/test/java/com/avaje/tests/batchload/TestBatchLazyWithCacheHits.java index 4da0caef4..a97ff8dfe 100644 --- a/src/test/java/com/avaje/tests/batchload/TestBatchLazyWithCacheHits.java +++ b/src/test/java/com/avaje/tests/batchload/TestBatchLazyWithCacheHits.java @@ -28,9 +28,6 @@ public class TestBatchLazyWithCacheHits extends BaseTestCase { inserted.add(insert(names[i])); } - ServerCacheManager serverCacheManager = Ebean.getServerCacheManager(); - serverCacheManager.setCaching(UUOne.class, true); - UUOne b = Ebean.find(UUOne.class) .setId(inserted.get(1).getId()) .setUseCache(true) diff --git a/src/test/java/com/avaje/tests/cache/TestQueryCacheCountry.java b/src/test/java/com/avaje/tests/cache/TestQueryCacheCountry.java index 1765dd6d3..95941de61 100644 --- a/src/test/java/com/avaje/tests/cache/TestQueryCacheCountry.java +++ b/src/test/java/com/avaje/tests/cache/TestQueryCacheCountry.java @@ -12,28 +12,33 @@ import com.avaje.ebean.cache.ServerCacheStatistics; import com.avaje.tests.model.basic.Country; import com.avaje.tests.model.basic.ResetBasicData; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + public class TestQueryCacheCountry extends BaseTestCase { @Test public void test() { ResetBasicData.reset(); - + + awaitL2Cache(); + ServerCache queryCache = Ebean.getServerCacheManager().getQueryCache(Country.class); queryCache.clear(); ServerCache beanCache = Ebean.getServerCacheManager().getBeanCache(Country.class); beanCache.clear(); - Assert.assertEquals(0, queryCache.getStatistics(false).getSize()); + assertEquals(0, queryCache.getStatistics(false).getSize()); List countryList0 = Ebean.find(Country.class) .setUseQueryCache(true) .order().asc("name") .findList(); - Assert.assertEquals(1, queryCache.getStatistics(false).getSize()); - Assert.assertTrue(countryList0.size() > 0); + assertEquals(1, queryCache.getStatistics(false).getSize()); + assertTrue(countryList0.size() > 0); List countryList1 = Ebean.find(Country.class) .setUseQueryCache(true) @@ -41,8 +46,8 @@ public class TestQueryCacheCountry extends BaseTestCase { .findList(); ServerCacheStatistics statistics = queryCache.getStatistics(false); - Assert.assertEquals(1, statistics.getSize()); - Assert.assertEquals(1, statistics.getHitCount()); + assertEquals(1, statistics.getSize()); + assertEquals(1, statistics.getHitCount()); Assert.assertSame(countryList1, countryList0); Country nz = Ebean.find(Country.class, "NZ"); @@ -51,7 +56,7 @@ public class TestQueryCacheCountry extends BaseTestCase { awaitL2Cache(); statistics = queryCache.getStatistics(false); - Assert.assertEquals(0, statistics.getSize()); + assertEquals(0, statistics.getSize()); List countryList2 = Ebean.find(Country.class) .setUseQueryCache(true) diff --git a/src/test/java/com/avaje/tests/model/basic/Article.java b/src/test/java/com/avaje/tests/model/basic/Article.java index d83365e05..fb70b9e86 100644 --- a/src/test/java/com/avaje/tests/model/basic/Article.java +++ b/src/test/java/com/avaje/tests/model/basic/Article.java @@ -1,6 +1,6 @@ package com.avaje.tests.model.basic; -import com.avaje.ebean.annotation.CacheStrategy; +import com.avaje.ebean.annotation.Cache; import com.avaje.ebean.annotation.CacheBeanTuning; import javax.persistence.CascadeType; @@ -10,7 +10,7 @@ import java.util.ArrayList; import java.util.List; -@CacheStrategy +@Cache @CacheBeanTuning(maxSecsToLive = 45) @Entity public class Article extends BasicDomain { diff --git a/src/test/java/com/avaje/tests/model/basic/Contact.java b/src/test/java/com/avaje/tests/model/basic/Contact.java index 69709ffda..d8c4e167c 100644 --- a/src/test/java/com/avaje/tests/model/basic/Contact.java +++ b/src/test/java/com/avaje/tests/model/basic/Contact.java @@ -1,6 +1,6 @@ package com.avaje.tests.model.basic; -import com.avaje.ebean.annotation.CacheStrategy; +import com.avaje.ebean.annotation.Cache; import com.avaje.ebean.annotation.ChangeLog; import com.avaje.ebean.annotation.CreatedTimestamp; import com.avaje.ebean.annotation.DocEmbedded; @@ -17,136 +17,134 @@ import java.sql.Timestamp; import java.util.List; @DocStore -@Index(columnNames = {"last_name","first_name"}) +@Index(columnNames = {"last_name", "first_name"}) @ChangeLog @Entity -@CacheStrategy(naturalKey="email") +@Cache(naturalKey = "email") public class Contact { - private static final long serialVersionUID = 1L; + @Id + int id; - @Id - int id; + String firstName; + String lastName; - String firstName; - String lastName; + String phone; + String mobile; + String email; - String phone; - String mobile; - String email; + @DocEmbedded(doc = "id,name") + @ManyToOne(optional = false) + Customer customer; - @DocEmbedded(doc="id,name") - @ManyToOne(optional=false) - Customer customer; - - @ManyToOne(optional=true) - ContactGroup group; - - @OneToMany(cascade = CascadeType.ALL) - List notes; + @ManyToOne(optional = true) + ContactGroup group; - @CreatedTimestamp - Timestamp cretime; + @OneToMany(cascade = CascadeType.ALL) + List notes; - @Version - Timestamp updtime; + @CreatedTimestamp + Timestamp cretime; + + @Version + Timestamp updtime; - public Contact(String firstName, String lastName) { - this.firstName = firstName; - this.lastName = lastName; - } + public Contact(String firstName, String lastName) { + this.firstName = firstName; + this.lastName = lastName; + } - public Contact() { + public Contact() { - } + } - public int getId() { - return id; - } + public int getId() { + return id; + } - public void setId(int id) { - this.id = id; - } + public void setId(int id) { + this.id = id; + } - public Timestamp getUpdtime() { - return updtime; - } + public Timestamp getUpdtime() { + return updtime; + } - public void setUpdtime(Timestamp updtime) { - this.updtime = updtime; - } + public void setUpdtime(Timestamp updtime) { + this.updtime = updtime; + } - public Timestamp getCretime() { - return cretime; - } + public Timestamp getCretime() { + return cretime; + } - public void setCretime(Timestamp cretime) { - this.cretime = cretime; - } + public void setCretime(Timestamp cretime) { + this.cretime = cretime; + } - public String getFirstName() { - return firstName; - } + public String getFirstName() { + return firstName; + } - public void setFirstName(String firstName) { - this.firstName = firstName; - } + public void setFirstName(String firstName) { + this.firstName = firstName; + } - public String getLastName() { - return lastName; - } + public String getLastName() { + return lastName; + } - public void setLastName(String lastName) { - this.lastName = lastName; - } + public void setLastName(String lastName) { + this.lastName = lastName; + } - public String getPhone() { - return phone; - } + public String getPhone() { + return phone; + } - public void setPhone(String phone) { - this.phone = phone; - } + public void setPhone(String phone) { + this.phone = phone; + } - public String getMobile() { - return mobile; - } + public String getMobile() { + return mobile; + } - public void setMobile(String mobile) { - this.mobile = mobile; - } + public void setMobile(String mobile) { + this.mobile = mobile; + } - public String getEmail() { - return email; - } + public String getEmail() { + return email; + } - public void setEmail(String email) { - this.email = email; - } + public void setEmail(String email) { + this.email = email; + } - public Customer getCustomer() { - return customer; - } + public Customer getCustomer() { + return customer; + } - public void setCustomer(Customer customer) { - this.customer = customer; - } - - public ContactGroup getGroup() { - return group; - } + public void setCustomer(Customer customer) { + this.customer = customer; + } - public void setGroup(ContactGroup group) { - this.group = group; - } + public ContactGroup getGroup() { + return group; + } - public List getNotes() { - return notes; - } + public void setGroup(ContactGroup group) { + this.group = group; + } - public void setNotes(List notes) { - this.notes = notes; - } + public List getNotes() { + return notes; + } + + public void setNotes(List notes) { + this.notes = notes; + } } diff --git a/src/test/java/com/avaje/tests/model/basic/Country.java b/src/test/java/com/avaje/tests/model/basic/Country.java index 1397b1aea..f8dea85de 100644 --- a/src/test/java/com/avaje/tests/model/basic/Country.java +++ b/src/test/java/com/avaje/tests/model/basic/Country.java @@ -1,6 +1,6 @@ package com.avaje.tests.model.basic; -import com.avaje.ebean.annotation.CacheStrategy; +import com.avaje.ebean.annotation.Cache; import com.avaje.ebean.annotation.CacheBeanTuning; import com.avaje.ebean.annotation.ChangeLog; import com.avaje.ebean.annotation.ChangeLogInsertMode; @@ -18,7 +18,7 @@ import javax.validation.constraints.Size; @DocStore @ReadAudit @ChangeLog(inserts = ChangeLogInsertMode.INCLUDE) -@CacheStrategy(readOnly = true) +@Cache(readOnly = true, enableQueryCache = true) @CacheBeanTuning(maxSize = 500) @Entity @Table(name = "o_country") diff --git a/src/test/java/com/avaje/tests/model/basic/Customer.java b/src/test/java/com/avaje/tests/model/basic/Customer.java index 5b57b03b6..bdc051bc3 100644 --- a/src/test/java/com/avaje/tests/model/basic/Customer.java +++ b/src/test/java/com/avaje/tests/model/basic/Customer.java @@ -1,5 +1,6 @@ package com.avaje.tests.model.basic; +import com.avaje.ebean.annotation.Cache; import com.avaje.ebean.annotation.ChangeLog; import com.avaje.ebean.annotation.ChangeLogInsertMode; import com.avaje.ebean.annotation.DbComment; @@ -26,6 +27,7 @@ import java.util.concurrent.locks.ReentrantLock; /** * Customer entity bean. */ +@Cache(enableQueryCache = true) @DocStore @ChangeLog(inserts = ChangeLogInsertMode.EXCLUDE, updatesThatInclude = {"name","status"}) @Entity diff --git a/src/test/java/com/avaje/tests/model/basic/EBasicChangeLog.java b/src/test/java/com/avaje/tests/model/basic/EBasicChangeLog.java index 93332f3c4..131a98d7a 100644 --- a/src/test/java/com/avaje/tests/model/basic/EBasicChangeLog.java +++ b/src/test/java/com/avaje/tests/model/basic/EBasicChangeLog.java @@ -1,5 +1,6 @@ package com.avaje.tests.model.basic; +import com.avaje.ebean.annotation.Cache; import com.avaje.ebean.annotation.ChangeLog; import com.avaje.ebean.annotation.ReadAudit; import com.avaje.ebean.annotation.WhenCreated; @@ -13,6 +14,7 @@ import javax.persistence.Version; import javax.validation.constraints.Size; import java.sql.Timestamp; +@Cache(enableQueryCache = true) @ReadAudit @ChangeLog(updatesThatInclude = {"name","shortDescription"}) @Entity diff --git a/src/test/java/com/avaje/tests/model/basic/EBasicVer.java b/src/test/java/com/avaje/tests/model/basic/EBasicVer.java index 2cb9273ae..f243903f2 100644 --- a/src/test/java/com/avaje/tests/model/basic/EBasicVer.java +++ b/src/test/java/com/avaje/tests/model/basic/EBasicVer.java @@ -1,5 +1,7 @@ package com.avaje.tests.model.basic; +import com.avaje.ebean.annotation.Cache; + import java.sql.Timestamp; import javax.persistence.Entity; @@ -7,6 +9,7 @@ import javax.persistence.Id; import javax.persistence.Table; import javax.persistence.Version; +@Cache(enableQueryCache = true) @Entity @Table(name = "e_basicver") public class EBasicVer { diff --git a/src/test/java/com/avaje/tests/model/basic/FeatureDescription.java b/src/test/java/com/avaje/tests/model/basic/FeatureDescription.java index 0fac2b2c6..a3489d907 100644 --- a/src/test/java/com/avaje/tests/model/basic/FeatureDescription.java +++ b/src/test/java/com/avaje/tests/model/basic/FeatureDescription.java @@ -4,9 +4,9 @@ import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; -import com.avaje.ebean.annotation.CacheStrategy; +import com.avaje.ebean.annotation.Cache; -@CacheStrategy(readOnly = true, useBeanCache = true) +@Cache(readOnly = true) @Entity @Table(name="feature_desc") public class FeatureDescription { diff --git a/src/test/java/com/avaje/tests/model/basic/OCachedBean.java b/src/test/java/com/avaje/tests/model/basic/OCachedBean.java index fa6f01a33..bb3bd40e6 100644 --- a/src/test/java/com/avaje/tests/model/basic/OCachedBean.java +++ b/src/test/java/com/avaje/tests/model/basic/OCachedBean.java @@ -10,12 +10,12 @@ import javax.persistence.ManyToMany; import javax.persistence.OneToMany; import javax.persistence.Table; -import com.avaje.ebean.annotation.CacheStrategy; +import com.avaje.ebean.annotation.Cache; /** * Cached bean for testing caching implementation. */ -@CacheStrategy +@Cache @Entity @Table(name = "o_cached_bean") public class OCachedBean { diff --git a/src/test/java/com/avaje/tests/model/basic/OCachedBeanChild.java b/src/test/java/com/avaje/tests/model/basic/OCachedBeanChild.java index 7d8b05e78..ce9f5f397 100644 --- a/src/test/java/com/avaje/tests/model/basic/OCachedBeanChild.java +++ b/src/test/java/com/avaje/tests/model/basic/OCachedBeanChild.java @@ -5,12 +5,12 @@ import javax.persistence.Id; import javax.persistence.ManyToOne; import javax.persistence.Table; -import com.avaje.ebean.annotation.CacheStrategy; +import com.avaje.ebean.annotation.Cache; /** * Cached bean for testing caching implementation, especially relations. */ -@CacheStrategy +@Cache @Entity @Table(name = "o_cached_bean_child") public class OCachedBeanChild { diff --git a/src/test/java/com/avaje/tests/model/basic/Order.java b/src/test/java/com/avaje/tests/model/basic/Order.java index 33ac9f33b..fc94f160c 100644 --- a/src/test/java/com/avaje/tests/model/basic/Order.java +++ b/src/test/java/com/avaje/tests/model/basic/Order.java @@ -1,5 +1,6 @@ package com.avaje.tests.model.basic; +import com.avaje.ebean.annotation.Cache; import com.avaje.ebean.annotation.ChangeLog; import com.avaje.ebean.annotation.DocEmbedded; import com.avaje.ebean.annotation.DocStore; @@ -30,6 +31,7 @@ import java.util.List; /** * Order entity bean. */ +@Cache @DocStore @ChangeLog @Entity diff --git a/src/test/java/com/avaje/tests/model/basic/OrderDetail.java b/src/test/java/com/avaje/tests/model/basic/OrderDetail.java index 72c4fabc9..272a2bff7 100644 --- a/src/test/java/com/avaje/tests/model/basic/OrderDetail.java +++ b/src/test/java/com/avaje/tests/model/basic/OrderDetail.java @@ -1,5 +1,6 @@ package com.avaje.tests.model.basic; +import com.avaje.ebean.annotation.Cache; import com.avaje.ebean.annotation.DocEmbedded; import javax.persistence.Entity; @@ -13,146 +14,147 @@ import java.sql.Timestamp; /** * Order Detail entity bean. */ +@Cache @Entity @Table(name = "o_order_detail") public class OrderDetail implements Serializable { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - @Id - Integer id; + @Id + Integer id; - @ManyToOne(optional = false) - Order order; + @ManyToOne(optional = false) + Order order; - Integer orderQty; + Integer orderQty; - Integer shipQty; + Integer shipQty; - Double unitPrice; + Double unitPrice; - @ManyToOne - @DocEmbedded(doc = "id,name,sku") - Product product; + @ManyToOne + @DocEmbedded(doc = "id,name,sku") + Product product; - Timestamp cretime; + Timestamp cretime; - @Version - Timestamp updtime; + @Version + Timestamp updtime; - public OrderDetail() { - } + public OrderDetail() { + } - public OrderDetail(Product product, Integer orderQty, Double unitPrice) { - this.product = product; - this.orderQty = orderQty; - this.unitPrice = unitPrice; - } + public OrderDetail(Product product, Integer orderQty, Double unitPrice) { + this.product = product; + this.orderQty = orderQty; + this.unitPrice = unitPrice; + } - /** - * Return id. - */ - public Integer getId() { - return id; - } + /** + * Return id. + */ + public Integer getId() { + return id; + } - /** - * Set id. - */ - public void setId(Integer id) { - this.id = id; - } + /** + * Set id. + */ + public void setId(Integer id) { + this.id = id; + } - /** - * Return order qty. - */ - public Integer getOrderQty() { - return orderQty; - } + /** + * Return order qty. + */ + public Integer getOrderQty() { + return orderQty; + } - /** - * Set order qty. - */ - public void setOrderQty(Integer orderQty) { - this.orderQty = orderQty; - } + /** + * Set order qty. + */ + public void setOrderQty(Integer orderQty) { + this.orderQty = orderQty; + } - /** - * Return ship qty. - */ - public Integer getShipQty() { - return shipQty; - } + /** + * Return ship qty. + */ + public Integer getShipQty() { + return shipQty; + } - /** - * Set ship qty. - */ - public void setShipQty(Integer shipQty) { - this.shipQty = shipQty; - } + /** + * Set ship qty. + */ + public void setShipQty(Integer shipQty) { + this.shipQty = shipQty; + } - public Double getUnitPrice() { - return unitPrice; - } + public Double getUnitPrice() { + return unitPrice; + } - public void setUnitPrice(Double unitPrice) { - this.unitPrice = unitPrice; - } + public void setUnitPrice(Double unitPrice) { + this.unitPrice = unitPrice; + } - /** - * Return cretime. - */ - public Timestamp getCretime() { - return cretime; - } + /** + * Return cretime. + */ + public Timestamp getCretime() { + return cretime; + } - /** - * Set cretime. - */ - public void setCretime(Timestamp cretime) { - this.cretime = cretime; - } + /** + * Set cretime. + */ + public void setCretime(Timestamp cretime) { + this.cretime = cretime; + } - /** - * Return updtime. - */ - public Timestamp getUpdtime() { - return updtime; - } + /** + * Return updtime. + */ + public Timestamp getUpdtime() { + return updtime; + } - /** - * Set updtime. - */ - public void setUpdtime(Timestamp updtime) { - this.updtime = updtime; - } + /** + * Set updtime. + */ + public void setUpdtime(Timestamp updtime) { + this.updtime = updtime; + } - /** - * Return order. - */ - public Order getOrder() { - return order; - } + /** + * Return order. + */ + public Order getOrder() { + return order; + } - /** - * Set order. - */ - public void setOrder(Order order) { - this.order = order; - } + /** + * Set order. + */ + public void setOrder(Order order) { + this.order = order; + } - /** - * Return product. - */ - public Product getProduct() { - return product; - } + /** + * Return product. + */ + public Product getProduct() { + return product; + } - /** - * Set product. - */ - public void setProduct(Product product) { - this.product = product; - } + /** + * Set product. + */ + public void setProduct(Product product) { + this.product = product; + } } diff --git a/src/test/java/com/avaje/tests/model/basic/Product.java b/src/test/java/com/avaje/tests/model/basic/Product.java index 320abd02c..c9cc1a00c 100644 --- a/src/test/java/com/avaje/tests/model/basic/Product.java +++ b/src/test/java/com/avaje/tests/model/basic/Product.java @@ -10,7 +10,7 @@ import javax.persistence.Version; import javax.validation.constraints.Size; import com.avaje.ebean.annotation.CacheQueryTuning; -import com.avaje.ebean.annotation.CacheStrategy; +import com.avaje.ebean.annotation.Cache; import com.avaje.ebean.annotation.CreatedTimestamp; import com.avaje.ebean.annotation.DocStore; @@ -18,7 +18,7 @@ import com.avaje.ebean.annotation.DocStore; * Product entity bean. */ @DocStore -@CacheStrategy +@Cache @CacheQueryTuning(maxSecsToLive = 15) @Entity @Table(name = "o_product") diff --git a/src/test/java/com/avaje/tests/model/basic/Section.java b/src/test/java/com/avaje/tests/model/basic/Section.java index 046df4b02..71a4f07f4 100644 --- a/src/test/java/com/avaje/tests/model/basic/Section.java +++ b/src/test/java/com/avaje/tests/model/basic/Section.java @@ -9,9 +9,9 @@ import javax.persistence.Lob; import javax.persistence.ManyToOne; import javax.persistence.OneToMany; -import com.avaje.ebean.annotation.CacheStrategy; +import com.avaje.ebean.annotation.Cache; -@CacheStrategy(useBeanCache=true) +@Cache @Entity public class Section extends BasicDomain { diff --git a/src/test/java/com/avaje/tests/model/basic/SubSection.java b/src/test/java/com/avaje/tests/model/basic/SubSection.java index ef89c30a5..6e42b9c12 100644 --- a/src/test/java/com/avaje/tests/model/basic/SubSection.java +++ b/src/test/java/com/avaje/tests/model/basic/SubSection.java @@ -3,9 +3,9 @@ package com.avaje.tests.model.basic; import javax.persistence.Entity; import javax.persistence.ManyToOne; -import com.avaje.ebean.annotation.CacheStrategy; +import com.avaje.ebean.annotation.Cache; -@CacheStrategy(useBeanCache=true) +@Cache @Entity public class SubSection extends BasicDomain { diff --git a/src/test/java/com/avaje/tests/model/basic/UUOne.java b/src/test/java/com/avaje/tests/model/basic/UUOne.java index e0ac0eb7a..8541f7d26 100644 --- a/src/test/java/com/avaje/tests/model/basic/UUOne.java +++ b/src/test/java/com/avaje/tests/model/basic/UUOne.java @@ -1,47 +1,49 @@ package com.avaje.tests.model.basic; -import java.util.List; -import java.util.UUID; +import com.avaje.ebean.annotation.Cache; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.OneToMany; +import java.util.List; +import java.util.UUID; +@Cache @Entity public class UUOne { - @Id - UUID id; - - String name; + @Id + UUID id; + + String name; - @OneToMany(cascade=CascadeType.ALL, mappedBy="master") - List comments; - - public UUID getId() { - return id; - } + @OneToMany(cascade = CascadeType.ALL, mappedBy = "master") + List comments; - public void setId(UUID id) { - this.id = id; - } + public UUID getId() { + return id; + } - public String getName() { - return name; - } + public void setId(UUID id) { + this.id = id; + } - public void setName(String name) { - this.name = name; - } + public String getName() { + return name; + } - public List getComments() { - return comments; - } + public void setName(String name) { + this.name = name; + } + + public List getComments() { + return comments; + } + + public void setComments(List comments) { + this.comments = comments; + } - public void setComments(List comments) { - this.comments = comments; - } - } diff --git a/src/test/java/com/avaje/tests/model/basic/cache/CInhOne.java b/src/test/java/com/avaje/tests/model/basic/cache/CInhOne.java index 648315480..ffe069d1f 100644 --- a/src/test/java/com/avaje/tests/model/basic/cache/CInhOne.java +++ b/src/test/java/com/avaje/tests/model/basic/cache/CInhOne.java @@ -1,12 +1,12 @@ package com.avaje.tests.model.basic.cache; -import com.avaje.ebean.annotation.CacheStrategy; +import com.avaje.ebean.annotation.Cache; import javax.persistence.DiscriminatorValue; import javax.persistence.Entity; import javax.persistence.Inheritance; -@CacheStrategy +@Cache @Entity @Inheritance @DiscriminatorValue("O") diff --git a/src/test/java/com/avaje/tests/model/basic/cache/CInhRoot.java b/src/test/java/com/avaje/tests/model/basic/cache/CInhRoot.java index 8563f13cf..bd2f5f04d 100644 --- a/src/test/java/com/avaje/tests/model/basic/cache/CInhRoot.java +++ b/src/test/java/com/avaje/tests/model/basic/cache/CInhRoot.java @@ -1,13 +1,13 @@ package com.avaje.tests.model.basic.cache; -import com.avaje.ebean.annotation.CacheStrategy; +import com.avaje.ebean.annotation.Cache; import com.avaje.tests.model.basic.BasicDomain; import javax.persistence.DiscriminatorColumn; import javax.persistence.Entity; import javax.persistence.Inheritance; -@CacheStrategy +@Cache @Entity @Inheritance @DiscriminatorColumn(length = 3) diff --git a/src/test/java/com/avaje/tests/model/basic/cache/CInhTwo.java b/src/test/java/com/avaje/tests/model/basic/cache/CInhTwo.java index dbc1a1726..254c2e932 100644 --- a/src/test/java/com/avaje/tests/model/basic/cache/CInhTwo.java +++ b/src/test/java/com/avaje/tests/model/basic/cache/CInhTwo.java @@ -1,12 +1,12 @@ package com.avaje.tests.model.basic.cache; -import com.avaje.ebean.annotation.CacheStrategy; +import com.avaje.ebean.annotation.Cache; import javax.persistence.DiscriminatorValue; import javax.persistence.Entity; import javax.persistence.Inheritance; -@CacheStrategy +@Cache @Entity @Inheritance @DiscriminatorValue("T") diff --git a/src/test/java/com/avaje/tests/model/embedded/EInvoice.java b/src/test/java/com/avaje/tests/model/embedded/EInvoice.java index e52e85d62..01a75f8f8 100644 --- a/src/test/java/com/avaje/tests/model/embedded/EInvoice.java +++ b/src/test/java/com/avaje/tests/model/embedded/EInvoice.java @@ -1,5 +1,7 @@ package com.avaje.tests.model.embedded; +import com.avaje.ebean.annotation.Cache; + import java.util.Date; import javax.persistence.AttributeOverride; @@ -11,6 +13,7 @@ import javax.persistence.Id; import javax.persistence.ManyToOne; import javax.persistence.Version; +@Cache @Entity public class EInvoice { diff --git a/src/test/java/com/avaje/tests/model/m2m/Permission.java b/src/test/java/com/avaje/tests/model/m2m/Permission.java index abde298f4..dc549f3ec 100644 --- a/src/test/java/com/avaje/tests/model/m2m/Permission.java +++ b/src/test/java/com/avaje/tests/model/m2m/Permission.java @@ -1,6 +1,6 @@ package com.avaje.tests.model.m2m; -import com.avaje.ebean.annotation.CacheStrategy; +import com.avaje.ebean.annotation.Cache; import javax.persistence.Column; import javax.persistence.Entity; @@ -14,7 +14,7 @@ import java.util.UUID; * The Class Permission. */ @Entity -@CacheStrategy(readOnly = true) +@Cache(readOnly = true) @Table(name = "mt_permission") public class Permission { diff --git a/src/test/java/com/avaje/tests/query/embedded/TestMultipleEmbeddedLoading.java b/src/test/java/com/avaje/tests/query/embedded/TestMultipleEmbeddedLoading.java index ff1dfa535..3f41df464 100644 --- a/src/test/java/com/avaje/tests/query/embedded/TestMultipleEmbeddedLoading.java +++ b/src/test/java/com/avaje/tests/query/embedded/TestMultipleEmbeddedLoading.java @@ -55,6 +55,8 @@ public class TestMultipleEmbeddedLoading extends BaseTestCase { invoice2.getBillAddress().setStreet("3 Pineapple St"); // bean should be dirty Ebean.save(invoice2); + + awaitL2Cache(); EInvoice invoice3 = Ebean.find(EInvoice.class) .where().idEq(invoice.getId()) diff --git a/src/test/java/com/avaje/tests/transaction/TestDeleteFromPersistenceContext.java b/src/test/java/com/avaje/tests/transaction/TestDeleteFromPersistenceContext.java index 52dbcb526..15050e22c 100644 --- a/src/test/java/com/avaje/tests/transaction/TestDeleteFromPersistenceContext.java +++ b/src/test/java/com/avaje/tests/transaction/TestDeleteFromPersistenceContext.java @@ -1,13 +1,15 @@ package com.avaje.tests.transaction; -import org.junit.Assert; -import org.junit.Test; - import com.avaje.ebean.BaseTestCase; import com.avaje.ebean.Ebean; import com.avaje.ebeaninternal.api.SpiTransaction; import com.avaje.tests.model.basic.EBasicVer; import com.avaje.tests.model.basic.ResetBasicData; +import org.junit.Test; + +import static junit.framework.TestCase.assertNull; +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertSame; public class TestDeleteFromPersistenceContext extends BaseTestCase { @@ -25,30 +27,33 @@ public class TestDeleteFromPersistenceContext extends BaseTestCase { try { EBasicVer bean2 = Ebean.find(EBasicVer.class, bean.getId()); - Assert.assertNotSame(bean, bean2); + assertNotSame(bean, bean2); EBasicVer bean3 = Ebean.find(EBasicVer.class, bean.getId()); // same instance from PersistenceContext - Assert.assertSame(bean2, bean3); + assertSame(bean2, bean3); Object bean4 = transaction.getPersistenceContext().get(EBasicVer.class, bean.getId()); - Assert.assertSame(bean2, bean4); + assertSame(bean2, bean4); Ebean.delete(bean2); Object bean5 = transaction.getPersistenceContext().get(EBasicVer.class, bean.getId()); - Assert.assertNull("Bean is deleted from PersistenceContext",bean5); - - EBasicVer bean6 = Ebean.find(EBasicVer.class).where().eq("id", bean.getId()).findUnique(); - Assert.assertNull("Bean where id eq is not found "+bean6, bean6); - - EBasicVer bean7 = Ebean.find(EBasicVer.class, bean.getId()); - Assert.assertNull("Bean is not expected to be found? "+bean7, bean7); - + assertNull("Bean is deleted from PersistenceContext",bean5); + + Ebean.commitTransaction(); + } finally { Ebean.endTransaction(); } - + + EBasicVer bean6 = Ebean.find(EBasicVer.class).where().eq("id", bean.getId()).findUnique(); + assertNull("Bean where id eq is not found "+bean6, bean6); + + awaitL2Cache(); + EBasicVer bean7 = Ebean.find(EBasicVer.class, bean.getId()); + assertNull("Bean is not expected to be found? "+bean7, bean7); + } } diff --git a/src/test/resources/logback-test.xml b/src/test/resources/logback-test.xml index e4fab19cc..466673fd5 100644 --- a/src/test/resources/logback-test.xml +++ b/src/test/resources/logback-test.xml @@ -72,7 +72,6 @@ - @@ -82,12 +81,14 @@ - - - + + + + +