Skip to content

SPR-16162 make JpaVendorAdapter configuration properties more transaction type aware #1591

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

Closed
wants to merge 1 commit into from
Closed
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 @@ -38,6 +38,7 @@
import javax.persistence.Query;
import javax.persistence.spi.PersistenceProvider;
import javax.persistence.spi.PersistenceUnitInfo;
import javax.persistence.spi.PersistenceUnitTransactionType;
import javax.sql.DataSource;

import org.apache.commons.logging.Log;
Expand Down Expand Up @@ -336,18 +337,20 @@ public void setBeanName(String name) {

@Override
public final void afterPropertiesSet() throws PersistenceException {
beforeAfterPropertiesSet();
if (this.jpaVendorAdapter != null) {
if (this.persistenceProvider == null) {
this.persistenceProvider = this.jpaVendorAdapter.getPersistenceProvider();
}
Map<String, ?> vendorPropertyMap = this.jpaVendorAdapter.getJpaPropertyMap();
if (vendorPropertyMap != null) {
vendorPropertyMap.forEach((key, value) -> {
if (!this.jpaPropertyMap.containsKey(key)) {
this.jpaPropertyMap.put(key, value);
}
});
vendorPropertyMap.forEach(this::addJpaPropertyIfNotExists);
}

PersistenceUnitTransactionType transactionType = determineTransactionType();
jpaVendorAdapter.getAdditionalJpaPropertyMapByTransactionType(transactionType)
.forEach(this::addJpaPropertyIfNotExists);

if (this.entityManagerFactoryInterface == null) {
this.entityManagerFactoryInterface = this.jpaVendorAdapter.getEntityManagerFactoryInterface();
if (!ClassUtils.isVisible(this.entityManagerFactoryInterface, this.beanClassLoader)) {
Expand Down Expand Up @@ -380,6 +383,21 @@ public final void afterPropertiesSet() throws PersistenceException {
this.entityManagerFactory = createEntityManagerFactoryProxy(this.nativeEntityManagerFactory);
}

@Nullable
protected PersistenceUnitTransactionType determineTransactionType() {
return null;
}

private void addJpaPropertyIfNotExists(String key, Object value) {
if (!this.jpaPropertyMap.containsKey(key)) {
this.jpaPropertyMap.put(key, value);
}
}

protected void beforeAfterPropertiesSet() {
// Allow subclasses to basically call afterPropertiesSet as well before this class
}

private EntityManagerFactory buildNativeEntityManagerFactory() {
EntityManagerFactory emf = createNativeEntityManagerFactory();
if (this.jpaVendorAdapter != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.spi.PersistenceProvider;
import javax.persistence.spi.PersistenceUnitTransactionType;

import org.springframework.lang.Nullable;

Expand Down Expand Up @@ -65,6 +66,20 @@ public interface JpaVendorAdapter {
@Nullable
Map<String, ?> getJpaPropertyMap();

/**
* Return a Map of vendor-specific JPA properties based on the transaction type,
* typically based on settings in this JpaVendorAdapter instance.
* <p>Note that there might be further JPA properties defined on
* the EntityManagerFactory bean, which might potentially override
* individual JPA property values specified here.
* @param transactionType the transaction type if can determine it or null if we can't
* @return a Map of JPA properties, as accepted by the standard
* JPA bootstrap facilities, or an empty Map if there are no such properties to expose
* @see javax.persistence.Persistence#createEntityManagerFactory(String, java.util.Map)
* @see javax.persistence.spi.PersistenceProvider#createContainerEntityManagerFactory(javax.persistence.spi.PersistenceUnitInfo, java.util.Map)
*/
Map<String, ?> getAdditionalJpaPropertyMapByTransactionType(@Nullable PersistenceUnitTransactionType transactionType);

/**
* Return the vendor-specific JpaDialect implementation for this
* provider, or {@code null} if there is none.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import javax.persistence.ValidationMode;
import javax.persistence.spi.PersistenceProvider;
import javax.persistence.spi.PersistenceUnitInfo;
import javax.persistence.spi.PersistenceUnitTransactionType;
import javax.sql.DataSource;

import org.springframework.beans.BeanUtils;
Expand Down Expand Up @@ -320,16 +321,19 @@ public void setResourceLoader(ResourceLoader resourceLoader) {
this.internalPersistenceUnitManager.setResourceLoader(resourceLoader);
}


@Override
protected EntityManagerFactory createNativeEntityManagerFactory() throws PersistenceException {
protected void beforeAfterPropertiesSet() {
PersistenceUnitManager managerToUse = this.persistenceUnitManager;
if (this.persistenceUnitManager == null) {
this.internalPersistenceUnitManager.afterPropertiesSet();
managerToUse = this.internalPersistenceUnitManager;
}

this.persistenceUnitInfo = determinePersistenceUnitInfo(managerToUse);
}

@Override
protected EntityManagerFactory createNativeEntityManagerFactory() throws PersistenceException {
JpaVendorAdapter jpaVendorAdapter = getJpaVendorAdapter();
if (jpaVendorAdapter != null && this.persistenceUnitInfo instanceof SmartPersistenceUnitInfo) {
String rootPackage = jpaVendorAdapter.getPersistenceProviderRootPackage();
Expand Down Expand Up @@ -392,6 +396,13 @@ protected PersistenceUnitInfo determinePersistenceUnitInfo(PersistenceUnitManage
protected void postProcessEntityManagerFactory(EntityManagerFactory emf, PersistenceUnitInfo pui) {
}

@Override
protected PersistenceUnitTransactionType determineTransactionType() {
if (this.persistenceUnitInfo != null) {
return this.persistenceUnitInfo.getTransactionType();
}
return super.determineTransactionType();
}

@Override
@Nullable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@

package org.springframework.orm.jpa.vendor;

import java.util.Collections;
import java.util.Map;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.spi.PersistenceUnitTransactionType;

import org.springframework.lang.Nullable;
import org.springframework.orm.jpa.JpaDialect;
Expand Down Expand Up @@ -129,6 +131,11 @@ public String getPersistenceProviderRootPackage() {
return null;
}

@Override
public Map<String, ?> getAdditionalJpaPropertyMapByTransactionType(@Nullable PersistenceUnitTransactionType transactionType) {
return Collections.emptyMap();
}

@Override
@Nullable
public JpaDialect getJpaDialect() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.spi.PersistenceProvider;
import javax.persistence.spi.PersistenceUnitTransactionType;

import org.hibernate.cfg.AvailableSettings;
import org.hibernate.dialect.DB2Dialect;
Expand All @@ -36,6 +37,8 @@

import org.springframework.lang.Nullable;

import static javax.persistence.spi.PersistenceUnitTransactionType.JTA;

/**
* {@link org.springframework.orm.jpa.JpaVendorAdapter} implementation for Hibernate
* EntityManager. Developed and tested against Hibernate 5.0, 5.1 and 5.2;
Expand Down Expand Up @@ -130,7 +133,13 @@ public Map<String, Object> getJpaPropertyMap() {
jpaProperties.put(AvailableSettings.SHOW_SQL, "true");
}

if (this.jpaDialect.prepareConnection) {
return jpaProperties;
}

@Override
public Map<String, ?> getAdditionalJpaPropertyMapByTransactionType(@Nullable PersistenceUnitTransactionType transactionType) {
Map<String, Object> jpaProperties = new HashMap<>();
if (this.jpaDialect.prepareConnection && transactionType != JTA) {
// Hibernate 5.1/5.2: manually enforce connection release mode ON_CLOSE (the former default)
try {
// Try Hibernate 5.2
Expand All @@ -148,7 +157,6 @@ public Map<String, Object> getJpaPropertyMap() {
}
}
}

return jpaProperties;
}

Expand Down