Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hibernate ORM configuration option to disable 2LC #7348

Merged
merged 3 commits into from
Feb 22, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,17 @@ public class HibernateOrmConfig {
@ConfigItem(name = "metrics.enabled", defaultValue = "false")
public boolean metricsEnabled;

/**
* The default in Quarkus is for 2nd level caching to be enabled,
* and a good implementation is already integrated for you.
* <p>
* Just cherry-pick which entities should be using the cache.
* <p>
* Set this to false to disable all 2nd level caches.
*/
@ConfigItem(defaultValue = "true")
public boolean secondLevelCachingEnabled;

public boolean isAnyPropertySet() {
return dialect.isPresent() ||
dialectStorageEngine.isPresent() ||
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

import static io.quarkus.deployment.annotations.ExecutionTime.RUNTIME_INIT;
import static io.quarkus.deployment.annotations.ExecutionTime.STATIC_INIT;
import static org.hibernate.cfg.AvailableSettings.JPA_SHARED_CACHE_MODE;
import static org.hibernate.cfg.AvailableSettings.USE_DIRECT_REFERENCE_CACHE_ENTRIES;
import static org.hibernate.cfg.AvailableSettings.USE_QUERY_CACHE;
import static org.hibernate.cfg.AvailableSettings.USE_SECOND_LEVEL_CACHE;

import java.io.IOException;
import java.net.URL;
Expand All @@ -17,12 +21,14 @@
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.Properties;
import java.util.Set;
import java.util.stream.Collectors;

import javax.enterprise.inject.Produces;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceUnit;
import javax.persistence.SharedCacheMode;
import javax.persistence.spi.PersistenceUnitTransactionType;

import org.eclipse.microprofile.metrics.Metadata;
Expand Down Expand Up @@ -672,10 +678,24 @@ private void handleHibernateORMWithNoPersistenceXml(
}

// Caching
Map<String, String> cacheConfigEntries = HibernateConfigUtil
.getCacheConfigEntries(hibernateConfig);
for (Entry<String, String> entry : cacheConfigEntries.entrySet()) {
desc.getProperties().setProperty(entry.getKey(), entry.getValue());
if (hibernateConfig.secondLevelCachingEnabled) {
Properties p = desc.getProperties();
//Only set these if the user isn't making an explicit choice:
p.putIfAbsent(USE_DIRECT_REFERENCE_CACHE_ENTRIES, Boolean.TRUE);
p.putIfAbsent(USE_SECOND_LEVEL_CACHE, Boolean.TRUE);
p.putIfAbsent(USE_QUERY_CACHE, Boolean.TRUE);
p.putIfAbsent(JPA_SHARED_CACHE_MODE, SharedCacheMode.ENABLE_SELECTIVE);
Map<String, String> cacheConfigEntries = HibernateConfigUtil.getCacheConfigEntries(hibernateConfig);
for (Entry<String, String> entry : cacheConfigEntries.entrySet()) {
desc.getProperties().setProperty(entry.getKey(), entry.getValue());
}
} else {
//Unless the global switch is explicitly set to off, in which case we disable all caching:
Properties p = desc.getProperties();
p.put(USE_DIRECT_REFERENCE_CACHE_ENTRIES, Boolean.FALSE);
p.put(USE_SECOND_LEVEL_CACHE, Boolean.FALSE);
p.put(USE_QUERY_CACHE, Boolean.FALSE);
p.put(JPA_SHARED_CACHE_MODE, SharedCacheMode.NONE);
}

descriptors.add(desc);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,11 @@
import static org.hibernate.cfg.AvailableSettings.JPA_JDBC_PASSWORD;
import static org.hibernate.cfg.AvailableSettings.JPA_JDBC_URL;
import static org.hibernate.cfg.AvailableSettings.JPA_JDBC_USER;
import static org.hibernate.cfg.AvailableSettings.JPA_SHARED_CACHE_MODE;
import static org.hibernate.cfg.AvailableSettings.JPA_TRANSACTION_TYPE;
import static org.hibernate.cfg.AvailableSettings.PASS;
import static org.hibernate.cfg.AvailableSettings.TRANSACTION_COORDINATOR_STRATEGY;
import static org.hibernate.cfg.AvailableSettings.URL;
import static org.hibernate.cfg.AvailableSettings.USER;
import static org.hibernate.cfg.AvailableSettings.USE_DIRECT_REFERENCE_CACHE_ENTRIES;
import static org.hibernate.cfg.AvailableSettings.USE_QUERY_CACHE;
import static org.hibernate.cfg.AvailableSettings.USE_SECOND_LEVEL_CACHE;
import static org.hibernate.cfg.AvailableSettings.WRAP_RESULT_SETS;
import static org.hibernate.cfg.AvailableSettings.XML_MAPPING_ENABLED;
import static org.hibernate.internal.HEMLogging.messageLogger;
Expand All @@ -33,7 +29,6 @@
import java.util.concurrent.ConcurrentHashMap;

import javax.persistence.PersistenceException;
import javax.persistence.SharedCacheMode;
import javax.persistence.spi.PersistenceUnitTransactionType;

import org.hibernate.boot.CacheRegionDefinition;
Expand Down Expand Up @@ -284,8 +279,6 @@ private MergedSettings mergeSettings(PersistenceUnitDescriptor persistenceUnit)
}
cfg.remove(JACC_ENABLED);

enableCachingByDefault(cfg);

// here we are going to iterate the merged config settings looking for:
// 1) additional JACC permissions
// 2) additional cache region declarations
Expand Down Expand Up @@ -327,17 +320,6 @@ private MergedSettings mergeSettings(PersistenceUnitDescriptor persistenceUnit)
return mergedSettings;
}

/**
* Enable 2LC for entities and queries by default. Also allow "reference caching" by default.
*/
private void enableCachingByDefault(final Map<String, Object> configurationValues) {
//Only set these if the user isn't making an explicit choice:
configurationValues.putIfAbsent(USE_DIRECT_REFERENCE_CACHE_ENTRIES, Boolean.TRUE);
configurationValues.putIfAbsent(USE_SECOND_LEVEL_CACHE, Boolean.TRUE);
configurationValues.putIfAbsent(USE_QUERY_CACHE, Boolean.TRUE);
configurationValues.putIfAbsent(JPA_SHARED_CACHE_MODE, SharedCacheMode.ENABLE_SELECTIVE);
}

public RecordedState build() {
MetadataImpl fullMeta = (MetadataImpl) MetadataBuildingProcess.complete(
managedResources,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@
import java.net.URL;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import javax.persistence.SharedCacheMode;
import javax.persistence.ValidationMode;
Expand Down Expand Up @@ -36,7 +34,7 @@ public LightPersistenceXmlDescriptor(final PersistenceUnitDescriptor toClone) {
this.validationMode = toClone.getValidationMode();
this.sharedCachemode = toClone.getSharedCacheMode();
this.managedClassNames = Collections.unmodifiableList(toClone.getManagedClassNames());
this.properties = filterNonStrings(toClone.getProperties());
this.properties = toClone.getProperties();
verifyIgnoredFields(toClone);
}

Expand All @@ -63,25 +61,6 @@ private static void verifyIgnoredFields(final PersistenceUnitDescriptor toClone)
}
}

private static final Properties filterNonStrings(final Properties properties) {
Properties clean = new Properties();
final Set<Map.Entry<Object, Object>> entries = properties.entrySet();
for (Map.Entry<Object, Object> e : entries) {
final Object key = e.getKey();
if (!(key instanceof String)) {
log.infof("Ignoring persistence unit property key '%s' as it's not a String", key);
continue;
}
final Object value = e.getValue();
if (!(value instanceof String)) {
log.infof("Ignoring persistence unit property for key '%s' as the value is not a String", key);
continue;
}
clean.setProperty((String) key, (String) value);
}
return clean;
}

@Override
public URL getPersistenceUnitRootUrl() {
return null;
Expand Down
5 changes: 5 additions & 0 deletions integration-tests/jpa/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5-internal</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import org.hibernate.cache.spi.TimestampsCache;
import org.hibernate.internal.SessionImpl;

import io.quarkus.runtime.LaunchMode;
import io.quarkus.runtime.configuration.ProfileManager;

Expand Down Expand Up @@ -96,4 +99,14 @@ public String getCake() {
Cake c = (Cake) em.createQuery("from Cake").getSingleResult();
return c.getType();
}

@GET
@Produces(MediaType.TEXT_PLAIN)
@Path("/timestamps")
public String checkCachingState() {
SessionImpl sessionImpl = em.unwrap(SessionImpl.class);
TimestampsCache timestampsCache = sessionImpl.getSessionFactory().getCache().getTimestampsCache();
return timestampsCache.getClass().getName();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package io.quarkus.it.jpa.configurationless;

import static org.hamcrest.core.StringContains.containsString;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.test.QuarkusUnitTest;
import io.restassured.RestAssured;

/**
* Similar to JPAConfigurationlessTest, yet explicitly disabling 2nd level caching,
* then asserting the TimestampsCacheDisabledImpl have been disabled as a consequence.
*/
public class JPACacheDisabled {

@RegisterExtension
static final QuarkusUnitTest config = new QuarkusUnitTest()
.withConfigurationResource("application.properties")
.overrideConfigKey("quarkus.hibernate-orm.second-level-caching-enabled", "false");

@Test
public void testInjection() {
RestAssured.when().get("/jpa-test").then()
.body(containsString("jpa=OK"));

RestAssured.when().get("/jpa-test/user-tx").then()
.body(containsString("jpa=OK"));

RestAssured.when().get("/jpa-test/timestamps").then()
.body(containsString("org.hibernate.cache.internal.TimestampsCacheDisabledImpl"));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,9 @@ public void testInjection() {

RestAssured.when().get("/jpa-test/user-tx").then()
.body(containsString("jpa=OK"));

RestAssured.when().get("/jpa-test/timestamps").then()
.body(containsString("org.hibernate.cache.internal.TimestampsCacheEnabledImpl"));
}

}