Upgrade to JPA 2.1+ and Bean Validation 1.1+; remove native support for Hibernate 3.6 and 4.x
Issue: SPR-13481 Issue: SPR-13827
This commit is contained in:
parent
69ec437fbc
commit
54004e0d78
|
|
@ -24,11 +24,13 @@ import java.lang.reflect.Method;
|
|||
import java.lang.reflect.Proxy;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import javax.validation.Configuration;
|
||||
import javax.validation.ConstraintValidatorFactory;
|
||||
import javax.validation.MessageInterpolator;
|
||||
import javax.validation.ParameterNameProvider;
|
||||
import javax.validation.TraversableResolver;
|
||||
import javax.validation.Validation;
|
||||
import javax.validation.ValidationProviderResolver;
|
||||
|
|
@ -66,14 +68,8 @@ import org.springframework.util.ReflectionUtils;
|
|||
* you will almost always use the default Validator anyway. This can also be injected directly
|
||||
* into any target dependency of type {@link org.springframework.validation.Validator}!
|
||||
*
|
||||
* <p><b>As of Spring 4.0, this class supports Bean Validation 1.0 and 1.1, with special support
|
||||
* for Hibernate Validator 4.3 and 5.x</b> (see {@link #setValidationMessageSource}).
|
||||
*
|
||||
* <p>Note that Bean Validation 1.1's {@code #forExecutables} method isn't supported: We do not
|
||||
* expect that method to be called by application code; consider {@link MethodValidationInterceptor}
|
||||
* instead. If you really need programmatic {@code #forExecutables} access, inject this class as
|
||||
* a {@link ValidatorFactory} and call {@link #getValidator()} on it, then {@code #forExecutables}
|
||||
* on the returned native {@link Validator} reference instead of directly on this class.
|
||||
* <p><b>As of Spring 5.0, this class requires Bean Validation 1.1, with special support
|
||||
* for Hibernate Validator 5.x</b> (see {@link #setValidationMessageSource}).
|
||||
*
|
||||
* <p>This class is also being used by Spring's MVC configuration namespace, in case of the
|
||||
* {@code javax.validation} API being present but no explicit Validator having been configured.
|
||||
|
|
@ -88,10 +84,6 @@ import org.springframework.util.ReflectionUtils;
|
|||
public class LocalValidatorFactoryBean extends SpringValidatorAdapter
|
||||
implements ValidatorFactory, ApplicationContextAware, InitializingBean, DisposableBean {
|
||||
|
||||
// Bean Validation 1.1 close() method available?
|
||||
private static final Method closeMethod = ClassUtils.getMethodIfAvailable(ValidatorFactory.class, "close");
|
||||
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private Class providerClass;
|
||||
|
||||
|
|
@ -305,55 +297,23 @@ public class LocalValidatorFactoryBean extends SpringValidatorAdapter
|
|||
}
|
||||
|
||||
private void configureParameterNameProviderIfPossible(Configuration<?> configuration) {
|
||||
try {
|
||||
Class<?> parameterNameProviderClass =
|
||||
ClassUtils.forName("javax.validation.ParameterNameProvider", getClass().getClassLoader());
|
||||
Method parameterNameProviderMethod =
|
||||
Configuration.class.getMethod("parameterNameProvider", parameterNameProviderClass);
|
||||
final Object defaultProvider = ReflectionUtils.invokeMethod(
|
||||
Configuration.class.getMethod("getDefaultParameterNameProvider"), configuration);
|
||||
final ParameterNameDiscoverer discoverer = this.parameterNameDiscoverer;
|
||||
Object parameterNameProvider = Proxy.newProxyInstance(getClass().getClassLoader(),
|
||||
new Class<?>[] {parameterNameProviderClass}, new InvocationHandler() {
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
if (method.getName().equals("getParameterNames")) {
|
||||
String[] result = null;
|
||||
if (args[0] instanceof Constructor) {
|
||||
result = discoverer.getParameterNames((Constructor<?>) args[0]);
|
||||
}
|
||||
else if (args[0] instanceof Method) {
|
||||
result = discoverer.getParameterNames((Method) args[0]);
|
||||
}
|
||||
if (result != null) {
|
||||
return Arrays.asList(result);
|
||||
}
|
||||
else {
|
||||
try {
|
||||
return method.invoke(defaultProvider, args);
|
||||
}
|
||||
catch (InvocationTargetException ex) {
|
||||
throw ex.getTargetException();
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// toString, equals, hashCode
|
||||
try {
|
||||
return method.invoke(this, args);
|
||||
}
|
||||
catch (InvocationTargetException ex) {
|
||||
throw ex.getTargetException();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
ReflectionUtils.invokeMethod(parameterNameProviderMethod, configuration, parameterNameProvider);
|
||||
|
||||
}
|
||||
catch (Exception ex) {
|
||||
// Bean Validation 1.1 API not available - simply not applying the ParameterNameDiscoverer
|
||||
}
|
||||
// TODO: inner class
|
||||
final ParameterNameDiscoverer discoverer = this.parameterNameDiscoverer;
|
||||
final ParameterNameProvider defaultProvider = configuration.getDefaultParameterNameProvider();
|
||||
configuration.parameterNameProvider(new ParameterNameProvider() {
|
||||
@Override
|
||||
public List<String> getParameterNames(Constructor<?> constructor) {
|
||||
String[] paramNames = discoverer.getParameterNames(constructor);
|
||||
return (paramNames != null ? Arrays.asList(paramNames) :
|
||||
defaultProvider.getParameterNames(constructor));
|
||||
}
|
||||
@Override
|
||||
public List<String> getParameterNames(Method method) {
|
||||
String[] paramNames = discoverer.getParameterNames(method);
|
||||
return (paramNames != null ? Arrays.asList(paramNames) :
|
||||
defaultProvider.getParameterNames(method));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -397,9 +357,14 @@ public class LocalValidatorFactoryBean extends SpringValidatorAdapter
|
|||
return this.validatorFactory.getConstraintValidatorFactory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParameterNameProvider getParameterNameProvider() {
|
||||
return this.validatorFactory.getParameterNameProvider();
|
||||
}
|
||||
|
||||
public void close() {
|
||||
if (closeMethod != null && this.validatorFactory != null) {
|
||||
ReflectionUtils.invokeMethod(closeMethod, this.validatorFactory);
|
||||
if (this.validatorFactory != null) {
|
||||
this.validatorFactory.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -26,7 +26,6 @@ import javax.validation.ValidatorFactory;
|
|||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.hibernate.validator.HibernateValidator;
|
||||
|
||||
import org.springframework.core.BridgeMethodResolver;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
|
|
@ -48,9 +47,8 @@ import org.springframework.validation.annotation.Validated;
|
|||
* at the type level of the containing target class, applying to all public service methods
|
||||
* of that class. By default, JSR-303 will validate against its default group only.
|
||||
*
|
||||
* <p>As of Spring 4.0, this functionality requires either a Bean Validation 1.1 provider
|
||||
* (such as Hibernate Validator 5.x) or the Bean Validation 1.0 API with Hibernate Validator
|
||||
* 4.3. The actual provider will be autodetected and automatically adapted.
|
||||
* <p>As of Spring 5.0, this functionality requires a Bean Validation 1.1 provider
|
||||
* (such as Hibernate Validator 5.x).
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.1
|
||||
|
|
@ -88,8 +86,7 @@ public class MethodValidationInterceptor implements MethodInterceptor {
|
|||
* Create a new MethodValidationInterceptor using a default JSR-303 validator underneath.
|
||||
*/
|
||||
public MethodValidationInterceptor() {
|
||||
this(forExecutablesMethod != null ? Validation.buildDefaultValidatorFactory() :
|
||||
HibernateValidatorDelegate.buildValidatorFactory());
|
||||
this(Validation.buildDefaultValidatorFactory());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -114,43 +111,36 @@ public class MethodValidationInterceptor implements MethodInterceptor {
|
|||
public Object invoke(MethodInvocation invocation) throws Throwable {
|
||||
Class<?>[] groups = determineValidationGroups(invocation);
|
||||
|
||||
if (forExecutablesMethod != null) {
|
||||
// Standard Bean Validation 1.1 API
|
||||
Object execVal = ReflectionUtils.invokeMethod(forExecutablesMethod, this.validator);
|
||||
Method methodToValidate = invocation.getMethod();
|
||||
Set<ConstraintViolation<?>> result;
|
||||
// Standard Bean Validation 1.1 API
|
||||
Object execVal = ReflectionUtils.invokeMethod(forExecutablesMethod, this.validator);
|
||||
Method methodToValidate = invocation.getMethod();
|
||||
Set<ConstraintViolation<?>> result;
|
||||
|
||||
try {
|
||||
result = (Set<ConstraintViolation<?>>) ReflectionUtils.invokeMethod(validateParametersMethod,
|
||||
execVal, invocation.getThis(), methodToValidate, invocation.getArguments(), groups);
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
// Probably a generic type mismatch between interface and impl as reported in SPR-12237 / HV-1011
|
||||
// Let's try to find the bridged method on the implementation class...
|
||||
methodToValidate = BridgeMethodResolver.findBridgedMethod(
|
||||
ClassUtils.getMostSpecificMethod(invocation.getMethod(), invocation.getThis().getClass()));
|
||||
result = (Set<ConstraintViolation<?>>) ReflectionUtils.invokeMethod(validateParametersMethod,
|
||||
execVal, invocation.getThis(), methodToValidate, invocation.getArguments(), groups);
|
||||
}
|
||||
if (!result.isEmpty()) {
|
||||
throw new ConstraintViolationException(result);
|
||||
}
|
||||
|
||||
Object returnValue = invocation.proceed();
|
||||
|
||||
result = (Set<ConstraintViolation<?>>) ReflectionUtils.invokeMethod(validateReturnValueMethod,
|
||||
execVal, invocation.getThis(), methodToValidate, returnValue, groups);
|
||||
if (!result.isEmpty()) {
|
||||
throw new ConstraintViolationException(result);
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
try {
|
||||
result = (Set<ConstraintViolation<?>>) ReflectionUtils.invokeMethod(validateParametersMethod,
|
||||
execVal, invocation.getThis(), methodToValidate, invocation.getArguments(), groups);
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
// Probably a generic type mismatch between interface and impl as reported in SPR-12237 / HV-1011
|
||||
// Let's try to find the bridged method on the implementation class...
|
||||
methodToValidate = BridgeMethodResolver.findBridgedMethod(
|
||||
ClassUtils.getMostSpecificMethod(invocation.getMethod(), invocation.getThis().getClass()));
|
||||
result = (Set<ConstraintViolation<?>>) ReflectionUtils.invokeMethod(validateParametersMethod,
|
||||
execVal, invocation.getThis(), methodToValidate, invocation.getArguments(), groups);
|
||||
}
|
||||
if (!result.isEmpty()) {
|
||||
throw new ConstraintViolationException(result);
|
||||
}
|
||||
|
||||
else {
|
||||
// Hibernate Validator 4.3's native API
|
||||
return HibernateValidatorDelegate.invokeWithinValidation(invocation, this.validator, groups);
|
||||
Object returnValue = invocation.proceed();
|
||||
|
||||
result = (Set<ConstraintViolation<?>>) ReflectionUtils.invokeMethod(validateReturnValueMethod,
|
||||
execVal, invocation.getThis(), methodToValidate, returnValue, groups);
|
||||
if (!result.isEmpty()) {
|
||||
throw new ConstraintViolationException(result);
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -168,36 +158,4 @@ public class MethodValidationInterceptor implements MethodInterceptor {
|
|||
return (validatedAnn != null ? validatedAnn.value() : new Class<?>[0]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Inner class to avoid a hard-coded Hibernate Validator 4.3 dependency.
|
||||
*/
|
||||
private static class HibernateValidatorDelegate {
|
||||
|
||||
public static ValidatorFactory buildValidatorFactory() {
|
||||
return Validation.byProvider(HibernateValidator.class).configure().buildValidatorFactory();
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static Object invokeWithinValidation(MethodInvocation invocation, Validator validator, Class<?>[] groups)
|
||||
throws Throwable {
|
||||
|
||||
org.hibernate.validator.method.MethodValidator methodValidator =
|
||||
validator.unwrap(org.hibernate.validator.method.MethodValidator.class);
|
||||
Set<org.hibernate.validator.method.MethodConstraintViolation<Object>> result =
|
||||
methodValidator.validateAllParameters(
|
||||
invocation.getThis(), invocation.getMethod(), invocation.getArguments(), groups);
|
||||
if (!result.isEmpty()) {
|
||||
throw new org.hibernate.validator.method.MethodConstraintViolationException(result);
|
||||
}
|
||||
Object returnValue = invocation.proceed();
|
||||
result = methodValidator.validateReturnValue(
|
||||
invocation.getThis(), invocation.getMethod(), returnValue, groups);
|
||||
if (!result.isEmpty()) {
|
||||
throw new org.hibernate.validator.method.MethodConstraintViolationException(result);
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import javax.validation.ConstraintViolation;
|
||||
import javax.validation.executable.ExecutableValidator;
|
||||
import javax.validation.metadata.BeanDescriptor;
|
||||
import javax.validation.metadata.ConstraintDescriptor;
|
||||
|
||||
|
|
@ -299,6 +300,11 @@ public class SpringValidatorAdapter implements SmartValidator, javax.validation.
|
|||
return (type != null ? this.targetValidator.unwrap(type) : (T) this.targetValidator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExecutableValidator forExecutables() {
|
||||
return this.targetValidator.forExecutables();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Wrapper for a String attribute which can be resolved via a {@code MessageSource},
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -31,10 +31,9 @@ import org.springframework.tests.sample.beans.TestBean;
|
|||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Tested against Hibernate Validator 4.3, as of Spring 4.0.
|
||||
* Tested against Hibernate Validator 5.x.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
*/
|
||||
public class BeanValidationPostProcessorTests {
|
||||
|
||||
|
|
@ -52,6 +51,7 @@ public class BeanValidationPostProcessorTests {
|
|||
assertTrue(ex.getRootCause().getMessage().contains("testBean"));
|
||||
assertTrue(ex.getRootCause().getMessage().contains("invalid"));
|
||||
}
|
||||
ac.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -63,6 +63,7 @@ public class BeanValidationPostProcessorTests {
|
|||
bd.getPropertyValues().add("testBean", new TestBean());
|
||||
ac.registerBeanDefinition("bean", bd);
|
||||
ac.refresh();
|
||||
ac.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -74,6 +75,7 @@ public class BeanValidationPostProcessorTests {
|
|||
ac.registerBeanDefinition("capp", new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class));
|
||||
ac.registerBeanDefinition("bean", new RootBeanDefinition(AfterInitConstraintBean.class));
|
||||
ac.refresh();
|
||||
ac.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -92,6 +94,7 @@ public class BeanValidationPostProcessorTests {
|
|||
assertTrue(ex.getRootCause().getMessage().contains("stringValue"));
|
||||
assertTrue(ex.getRootCause().getMessage().contains("invalid"));
|
||||
}
|
||||
ac.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -103,6 +106,7 @@ public class BeanValidationPostProcessorTests {
|
|||
bd.getPropertyValues().add("stringValue", "ss");
|
||||
ac.registerBeanDefinition("bean", bd);
|
||||
ac.refresh();
|
||||
ac.close();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -35,11 +35,11 @@ import org.springframework.validation.annotation.Validated;
|
|||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Tested against Hibernate Validator 4.3, as of Spring 4.0.
|
||||
* Tests against Hibernate Validator 5.x.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.1
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public class MethodValidationTests {
|
||||
|
||||
@Test
|
||||
|
|
@ -65,6 +65,7 @@ public class MethodValidationTests {
|
|||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void doTestProxyValidation(MyValidInterface proxy) {
|
||||
assertNotNull(proxy.myValidMethod("value", 5));
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -38,6 +38,10 @@ import javax.validation.constraints.NotNull;
|
|||
import org.hibernate.validator.HibernateValidator;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.validation.BeanPropertyBindingResult;
|
||||
import org.springframework.validation.Errors;
|
||||
import org.springframework.validation.FieldError;
|
||||
|
|
@ -47,10 +51,9 @@ import static org.hamcrest.Matchers.*;
|
|||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Tested against Hibernate Validator 4.3, as of Spring 4.0.
|
||||
* Tests against Hibernate Validator 5.x.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
*/
|
||||
public class ValidatorFactoryTests {
|
||||
|
||||
|
|
@ -58,6 +61,7 @@ public class ValidatorFactoryTests {
|
|||
public void testSimpleValidation() throws Exception {
|
||||
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||
validator.afterPropertiesSet();
|
||||
|
||||
ValidPerson person = new ValidPerson();
|
||||
Set<ConstraintViolation<ValidPerson>> result = validator.validate(person);
|
||||
assertEquals(2, result.size());
|
||||
|
|
@ -78,6 +82,7 @@ public class ValidatorFactoryTests {
|
|||
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||
validator.setProviderClass(HibernateValidator.class);
|
||||
validator.afterPropertiesSet();
|
||||
|
||||
ValidPerson person = new ValidPerson();
|
||||
Set<ConstraintViolation<ValidPerson>> result = validator.validate(person);
|
||||
assertEquals(2, result.size());
|
||||
|
|
@ -112,6 +117,7 @@ public class ValidatorFactoryTests {
|
|||
public void testSpringValidationFieldType() throws Exception {
|
||||
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||
validator.afterPropertiesSet();
|
||||
|
||||
ValidPerson person = new ValidPerson();
|
||||
person.setName("Phil");
|
||||
person.getAddress().setStreet("Phil's Street");
|
||||
|
|
@ -126,6 +132,7 @@ public class ValidatorFactoryTests {
|
|||
public void testSpringValidation() throws Exception {
|
||||
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||
validator.afterPropertiesSet();
|
||||
|
||||
ValidPerson person = new ValidPerson();
|
||||
BeanPropertyBindingResult result = new BeanPropertyBindingResult(person, "person");
|
||||
validator.validate(person, result);
|
||||
|
|
@ -153,6 +160,7 @@ public class ValidatorFactoryTests {
|
|||
public void testSpringValidationWithClassLevel() throws Exception {
|
||||
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||
validator.afterPropertiesSet();
|
||||
|
||||
ValidPerson person = new ValidPerson();
|
||||
person.setName("Juergen");
|
||||
person.getAddress().setStreet("Juergen's Street");
|
||||
|
|
@ -166,10 +174,32 @@ public class ValidatorFactoryTests {
|
|||
assertTrue(errorCodes.contains("NameAddressValid"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpringValidationWithAutowiredValidator() throws Exception {
|
||||
ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(
|
||||
LocalValidatorFactoryBean.class);
|
||||
LocalValidatorFactoryBean validator = ctx.getBean(LocalValidatorFactoryBean.class);
|
||||
|
||||
ValidPerson person = new ValidPerson();
|
||||
person.expectsAutowiredValidator = true;
|
||||
person.setName("Juergen");
|
||||
person.getAddress().setStreet("Juergen's Street");
|
||||
BeanPropertyBindingResult result = new BeanPropertyBindingResult(person, "person");
|
||||
validator.validate(person, result);
|
||||
assertEquals(1, result.getErrorCount());
|
||||
ObjectError globalError = result.getGlobalError();
|
||||
List<String> errorCodes = Arrays.asList(globalError.getCodes());
|
||||
assertEquals(2, errorCodes.size());
|
||||
assertTrue(errorCodes.contains("NameAddressValid.person"));
|
||||
assertTrue(errorCodes.contains("NameAddressValid"));
|
||||
ctx.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpringValidationWithErrorInListElement() throws Exception {
|
||||
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||
validator.afterPropertiesSet();
|
||||
|
||||
ValidPerson person = new ValidPerson();
|
||||
person.getAddressList().add(new ValidAddress());
|
||||
BeanPropertyBindingResult result = new BeanPropertyBindingResult(person, "person");
|
||||
|
|
@ -187,6 +217,7 @@ public class ValidatorFactoryTests {
|
|||
public void testSpringValidationWithErrorInSetElement() throws Exception {
|
||||
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||
validator.afterPropertiesSet();
|
||||
|
||||
ValidPerson person = new ValidPerson();
|
||||
person.getAddressSet().add(new ValidAddress());
|
||||
BeanPropertyBindingResult result = new BeanPropertyBindingResult(person, "person");
|
||||
|
|
@ -240,6 +271,8 @@ public class ValidatorFactoryTests {
|
|||
@Valid
|
||||
private Set<ValidAddress> addressSet = new LinkedHashSet<ValidAddress>();
|
||||
|
||||
public boolean expectsAutowiredValidator = false;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
|
@ -304,16 +337,22 @@ public class ValidatorFactoryTests {
|
|||
|
||||
public static class NameAddressValidator implements ConstraintValidator<NameAddressValid, ValidPerson> {
|
||||
|
||||
@Autowired
|
||||
private Environment environment;
|
||||
|
||||
@Override
|
||||
public void initialize(NameAddressValid constraintAnnotation) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid(ValidPerson value, ConstraintValidatorContext context) {
|
||||
if (value.expectsAutowiredValidator) {
|
||||
assertNotNull(this.environment);
|
||||
}
|
||||
boolean valid = (value.name == null || !value.address.street.contains(value.name));
|
||||
if (!valid && "Phil".equals(value.name)) {
|
||||
context.buildConstraintViolationWithTemplate(
|
||||
context.getDefaultConstraintMessageTemplate()).addNode("address").addConstraintViolation().disableDefaultConstraintViolation();
|
||||
context.getDefaultConstraintMessageTemplate()).addPropertyNode("address").addConstraintViolation().disableDefaultConstraintViolation();
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
|
@ -378,7 +417,7 @@ public class ValidatorFactoryTests {
|
|||
public boolean isValid(InnerBean bean, ConstraintValidatorContext context) {
|
||||
context.disableDefaultConstraintViolation();
|
||||
if (bean.getValue() == null) {
|
||||
context.buildConstraintViolationWithTemplate("NULL"). addNode("value").addConstraintViolation();
|
||||
context.buildConstraintViolationWithTemplate("NULL").addPropertyNode("value").addConstraintViolation();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -1,161 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate4;
|
||||
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import javax.transaction.Status;
|
||||
import javax.transaction.Synchronization;
|
||||
import javax.transaction.SystemException;
|
||||
import javax.transaction.Transaction;
|
||||
import javax.transaction.TransactionManager;
|
||||
import javax.transaction.TransactionSynchronizationRegistry;
|
||||
import javax.transaction.UserTransaction;
|
||||
|
||||
import org.hibernate.TransactionException;
|
||||
import org.hibernate.service.Service;
|
||||
|
||||
import org.springframework.transaction.jta.UserTransactionAdapter;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Implementation of Hibernate 4's JtaPlatform SPI (which has a different package
|
||||
* location in Hibernate 4.0-4.2 vs 4.3), exposing passed-in {@link TransactionManager},
|
||||
* {@link UserTransaction} and {@link TransactionSynchronizationRegistry} references.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.1.2
|
||||
*/
|
||||
@SuppressWarnings({"serial", "unchecked"})
|
||||
class ConfigurableJtaPlatform implements InvocationHandler {
|
||||
|
||||
static final Class<? extends Service> jtaPlatformClass;
|
||||
|
||||
static {
|
||||
Class<?> jpClass;
|
||||
try {
|
||||
// Try Hibernate 4.0-4.2 JtaPlatform variant
|
||||
jpClass = ClassUtils.forName("org.hibernate.service.jta.platform.spi.JtaPlatform",
|
||||
ConfigurableJtaPlatform.class.getClassLoader());
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
try {
|
||||
// Try Hibernate 4.3 JtaPlatform variant
|
||||
jpClass = ClassUtils.forName("org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform",
|
||||
ConfigurableJtaPlatform.class.getClassLoader());
|
||||
}
|
||||
catch (ClassNotFoundException ex2) {
|
||||
throw new IllegalStateException("Neither Hibernate 4.0-4.2 nor 4.3 variant of JtaPlatform found");
|
||||
}
|
||||
}
|
||||
jtaPlatformClass = (Class<? extends Service>) jpClass;
|
||||
}
|
||||
|
||||
static String getJtaPlatformBasePackage() {
|
||||
String className = jtaPlatformClass.getName();
|
||||
return className.substring(0, className.length() - "spi.JtaPlatform".length());
|
||||
}
|
||||
|
||||
|
||||
private final TransactionManager transactionManager;
|
||||
|
||||
private final UserTransaction userTransaction;
|
||||
|
||||
private final TransactionSynchronizationRegistry transactionSynchronizationRegistry;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new ConfigurableJtaPlatform instance with the given
|
||||
* JTA TransactionManager and optionally a given UserTransaction.
|
||||
* @param tm the JTA TransactionManager reference (required)
|
||||
* @param ut the JTA UserTransaction reference (optional)
|
||||
* @param tsr the JTA 1.1 TransactionSynchronizationRegistry (optional)
|
||||
*/
|
||||
public ConfigurableJtaPlatform(TransactionManager tm, UserTransaction ut, TransactionSynchronizationRegistry tsr) {
|
||||
Assert.notNull(tm, "TransactionManager reference must not be null");
|
||||
this.transactionManager = tm;
|
||||
this.userTransaction = (ut != null ? ut : new UserTransactionAdapter(tm));
|
||||
this.transactionSynchronizationRegistry = tsr;
|
||||
}
|
||||
|
||||
|
||||
public TransactionManager retrieveTransactionManager() {
|
||||
return this.transactionManager;
|
||||
}
|
||||
|
||||
public UserTransaction retrieveUserTransaction() {
|
||||
return this.userTransaction;
|
||||
}
|
||||
|
||||
public Object getTransactionIdentifier(Transaction transaction) {
|
||||
return transaction;
|
||||
}
|
||||
|
||||
public boolean canRegisterSynchronization() {
|
||||
try {
|
||||
return (this.transactionManager.getStatus() == Status.STATUS_ACTIVE);
|
||||
}
|
||||
catch (SystemException ex) {
|
||||
throw new TransactionException("Could not determine JTA transaction status", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void registerSynchronization(Synchronization synchronization) {
|
||||
if (this.transactionSynchronizationRegistry != null) {
|
||||
this.transactionSynchronizationRegistry.registerInterposedSynchronization(synchronization);
|
||||
}
|
||||
else {
|
||||
try {
|
||||
this.transactionManager.getTransaction().registerSynchronization(synchronization);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new TransactionException("Could not access JTA Transaction to register synchronization", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int getCurrentStatus() throws SystemException {
|
||||
return this.transactionManager.getStatus();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
try {
|
||||
return getClass().getMethod(method.getName(), method.getParameterTypes()).invoke(this, args);
|
||||
}
|
||||
catch (InvocationTargetException ex) {
|
||||
throw ex.getTargetException();
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
throw new IllegalStateException("Failed to delegate to corresponding implementation method", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain a proxy that implements the current Hibernate version's JtaPlatform interface
|
||||
* in the right package location, delegating all invocations to the same-named methods
|
||||
* on this ConfigurableJtaPlatform class itself.
|
||||
*/
|
||||
public Object getJtaPlatformProxy() {
|
||||
return Proxy.newProxyInstance(getClass().getClassLoader(), new Class<?>[] {jtaPlatformClass}, this);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate4;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.Session;
|
||||
|
||||
/**
|
||||
* Callback interface for Hibernate code. To be used with {@link HibernateTemplate}'s
|
||||
* execution methods, often as anonymous classes within a method implementation.
|
||||
* A typical implementation will call {@code Session.load/find/update} to perform
|
||||
* some operations on persistent objects.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.0.1
|
||||
* @see HibernateTemplate
|
||||
* @see HibernateTransactionManager
|
||||
*/
|
||||
public interface HibernateCallback<T> {
|
||||
|
||||
/**
|
||||
* Gets called by {@code HibernateTemplate.execute} with an active
|
||||
* Hibernate {@code Session}. Does not need to care about activating
|
||||
* or closing the {@code Session}, or handling transactions.
|
||||
* <p>Allows for returning a result object created within the callback,
|
||||
* i.e. a domain object or a collection of domain objects.
|
||||
* A thrown custom RuntimeException is treated as an application exception:
|
||||
* It gets propagated to the caller of the template.
|
||||
* @param session active Hibernate session
|
||||
* @return a result object, or {@code null} if none
|
||||
* @throws HibernateException if thrown by the Hibernate API
|
||||
* @see HibernateTemplate#execute
|
||||
*/
|
||||
T doInHibernate(Session session) throws HibernateException;
|
||||
|
||||
}
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate4;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
||||
|
||||
/**
|
||||
* {@link PersistenceExceptionTranslator} capable of translating {@link HibernateException}
|
||||
* instances to Spring's {@link DataAccessException} hierarchy.
|
||||
*
|
||||
* <p>Extended by {@link LocalSessionFactoryBean}, so there is no need to declare this
|
||||
* translator in addition to a {@code LocalSessionFactoryBean}.
|
||||
*
|
||||
* <p>When configuring the container with {@code @Configuration} classes, a {@code @Bean}
|
||||
* of this type must be registered manually.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.1
|
||||
* @see org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor
|
||||
* @see SessionFactoryUtils#convertHibernateAccessException(HibernateException)
|
||||
*/
|
||||
public class HibernateExceptionTranslator implements PersistenceExceptionTranslator {
|
||||
|
||||
@Override
|
||||
public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
|
||||
if (ex instanceof HibernateException) {
|
||||
return convertHibernateAccessException((HibernateException) ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given HibernateException to an appropriate exception from the
|
||||
* {@code org.springframework.dao} hierarchy.
|
||||
* @param ex HibernateException that occured
|
||||
* @return a corresponding DataAccessException
|
||||
* @see SessionFactoryUtils#convertHibernateAccessException
|
||||
*/
|
||||
protected DataAccessException convertHibernateAccessException(HibernateException ex) {
|
||||
return SessionFactoryUtils.convertHibernateAccessException(ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate4;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.hibernate.JDBCException;
|
||||
|
||||
import org.springframework.dao.UncategorizedDataAccessException;
|
||||
|
||||
/**
|
||||
* Hibernate-specific subclass of UncategorizedDataAccessException,
|
||||
* for JDBC exceptions that Hibernate wrapped.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.1
|
||||
* @see SessionFactoryUtils#convertHibernateAccessException
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class HibernateJdbcException extends UncategorizedDataAccessException {
|
||||
|
||||
public HibernateJdbcException(JDBCException ex) {
|
||||
super("JDBC exception on Hibernate data access: SQLException for SQL [" + ex.getSQL() + "]; SQL state [" +
|
||||
ex.getSQLState() + "]; error code [" + ex.getErrorCode() + "]; " + ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the underlying SQLException.
|
||||
*/
|
||||
public SQLException getSQLException() {
|
||||
return ((JDBCException) getCause()).getSQLException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the SQL that led to the problem.
|
||||
*/
|
||||
public String getSql() {
|
||||
return ((JDBCException) getCause()).getSQL();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate4;
|
||||
|
||||
import org.hibernate.UnresolvableObjectException;
|
||||
import org.hibernate.WrongClassException;
|
||||
|
||||
import org.springframework.orm.ObjectRetrievalFailureException;
|
||||
|
||||
/**
|
||||
* Hibernate-specific subclass of ObjectRetrievalFailureException.
|
||||
* Converts Hibernate's UnresolvableObjectException and WrongClassException.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.1
|
||||
* @see SessionFactoryUtils#convertHibernateAccessException
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class HibernateObjectRetrievalFailureException extends ObjectRetrievalFailureException {
|
||||
|
||||
public HibernateObjectRetrievalFailureException(UnresolvableObjectException ex) {
|
||||
super(ex.getEntityName(), ex.getIdentifier(), ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
public HibernateObjectRetrievalFailureException(WrongClassException ex) {
|
||||
super(ex.getEntityName(), ex.getIdentifier(), ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,795 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate4;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.Filter;
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.ReplicationMode;
|
||||
import org.hibernate.criterion.DetachedCriteria;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
|
||||
/**
|
||||
* Interface that specifies a basic set of Hibernate operations,
|
||||
* implemented by {@link HibernateTemplate}. Not often used, but a useful
|
||||
* option to enhance testability, as it can easily be mocked or stubbed.
|
||||
*
|
||||
* <p>Defines {@code HibernateTemplate}'s data access methods that
|
||||
* mirror various {@link org.hibernate.Session} methods. Users are
|
||||
* strongly encouraged to read the Hibernate {@code Session} javadocs
|
||||
* for details on the semantics of those methods.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.0.1
|
||||
* @see HibernateTemplate
|
||||
* @see org.hibernate.Session
|
||||
* @see HibernateTransactionManager
|
||||
*/
|
||||
public interface HibernateOperations {
|
||||
|
||||
/**
|
||||
* Execute the action specified by the given action object within a
|
||||
* {@link org.hibernate.Session}.
|
||||
* <p>Application exceptions thrown by the action object get propagated
|
||||
* to the caller (can only be unchecked). Hibernate exceptions are
|
||||
* transformed into appropriate DAO ones. Allows for returning a result
|
||||
* object, that is a domain object or a collection of domain objects.
|
||||
* <p>Note: Callback code is not supposed to handle transactions itself!
|
||||
* Use an appropriate transaction manager like
|
||||
* {@link HibernateTransactionManager}. Generally, callback code must not
|
||||
* touch any {@code Session} lifecycle methods, like close,
|
||||
* disconnect, or reconnect, to let the template do its work.
|
||||
* @param action callback object that specifies the Hibernate action
|
||||
* @return a result object returned by the action, or {@code null}
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see HibernateTransactionManager
|
||||
* @see org.hibernate.Session
|
||||
*/
|
||||
<T> T execute(HibernateCallback<T> action) throws DataAccessException;
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Convenience methods for loading individual objects
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Return the persistent instance of the given entity class
|
||||
* with the given identifier, or {@code null} if not found.
|
||||
* <p>This method is a thin wrapper around
|
||||
* {@link org.hibernate.Session#get(Class, java.io.Serializable)} for convenience.
|
||||
* For an explanation of the exact semantics of this method, please do refer to
|
||||
* the Hibernate API documentation in the first instance.
|
||||
* @param entityClass a persistent class
|
||||
* @param id the identifier of the persistent instance
|
||||
* @return the persistent instance, or {@code null} if not found
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#get(Class, java.io.Serializable)
|
||||
*/
|
||||
<T> T get(Class<T> entityClass, Serializable id) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Return the persistent instance of the given entity class
|
||||
* with the given identifier, or {@code null} if not found.
|
||||
* <p>Obtains the specified lock mode if the instance exists.
|
||||
* <p>This method is a thin wrapper around
|
||||
* {@link org.hibernate.Session#get(Class, java.io.Serializable, LockMode)} for convenience.
|
||||
* For an explanation of the exact semantics of this method, please do refer to
|
||||
* the Hibernate API documentation in the first instance.
|
||||
* @param entityClass a persistent class
|
||||
* @param id the identifier of the persistent instance
|
||||
* @param lockMode the lock mode to obtain
|
||||
* @return the persistent instance, or {@code null} if not found
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#get(Class, java.io.Serializable, org.hibernate.LockMode)
|
||||
*/
|
||||
<T> T get(Class<T> entityClass, Serializable id, LockMode lockMode) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Return the persistent instance of the given entity class
|
||||
* with the given identifier, or {@code null} if not found.
|
||||
* <p>This method is a thin wrapper around
|
||||
* {@link org.hibernate.Session#get(String, java.io.Serializable)} for convenience.
|
||||
* For an explanation of the exact semantics of this method, please do refer to
|
||||
* the Hibernate API documentation in the first instance.
|
||||
* @param entityName the name of the persistent entity
|
||||
* @param id the identifier of the persistent instance
|
||||
* @return the persistent instance, or {@code null} if not found
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#get(Class, java.io.Serializable)
|
||||
*/
|
||||
Object get(String entityName, Serializable id) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Return the persistent instance of the given entity class
|
||||
* with the given identifier, or {@code null} if not found.
|
||||
* Obtains the specified lock mode if the instance exists.
|
||||
* <p>This method is a thin wrapper around
|
||||
* {@link org.hibernate.Session#get(String, java.io.Serializable, LockMode)} for convenience.
|
||||
* For an explanation of the exact semantics of this method, please do refer to
|
||||
* the Hibernate API documentation in the first instance.
|
||||
* @param entityName the name of the persistent entity
|
||||
* @param id the identifier of the persistent instance
|
||||
* @param lockMode the lock mode to obtain
|
||||
* @return the persistent instance, or {@code null} if not found
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#get(Class, java.io.Serializable, org.hibernate.LockMode)
|
||||
*/
|
||||
Object get(String entityName, Serializable id, LockMode lockMode) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Return the persistent instance of the given entity class
|
||||
* with the given identifier, throwing an exception if not found.
|
||||
* <p>This method is a thin wrapper around
|
||||
* {@link org.hibernate.Session#load(Class, java.io.Serializable)} for convenience.
|
||||
* For an explanation of the exact semantics of this method, please do refer to
|
||||
* the Hibernate API documentation in the first instance.
|
||||
* @param entityClass a persistent class
|
||||
* @param id the identifier of the persistent instance
|
||||
* @return the persistent instance
|
||||
* @throws org.springframework.orm.ObjectRetrievalFailureException if not found
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#load(Class, java.io.Serializable)
|
||||
*/
|
||||
<T> T load(Class<T> entityClass, Serializable id) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Return the persistent instance of the given entity class
|
||||
* with the given identifier, throwing an exception if not found.
|
||||
* Obtains the specified lock mode if the instance exists.
|
||||
* <p>This method is a thin wrapper around
|
||||
* {@link org.hibernate.Session#load(Class, java.io.Serializable, LockMode)} for convenience.
|
||||
* For an explanation of the exact semantics of this method, please do refer to
|
||||
* the Hibernate API documentation in the first instance.
|
||||
* @param entityClass a persistent class
|
||||
* @param id the identifier of the persistent instance
|
||||
* @param lockMode the lock mode to obtain
|
||||
* @return the persistent instance
|
||||
* @throws org.springframework.orm.ObjectRetrievalFailureException if not found
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#load(Class, java.io.Serializable)
|
||||
*/
|
||||
<T> T load(Class<T> entityClass, Serializable id, LockMode lockMode) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Return the persistent instance of the given entity class
|
||||
* with the given identifier, throwing an exception if not found.
|
||||
* <p>This method is a thin wrapper around
|
||||
* {@link org.hibernate.Session#load(String, java.io.Serializable)} for convenience.
|
||||
* For an explanation of the exact semantics of this method, please do refer to
|
||||
* the Hibernate API documentation in the first instance.
|
||||
* @param entityName the name of the persistent entity
|
||||
* @param id the identifier of the persistent instance
|
||||
* @return the persistent instance
|
||||
* @throws org.springframework.orm.ObjectRetrievalFailureException if not found
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#load(Class, java.io.Serializable)
|
||||
*/
|
||||
Object load(String entityName, Serializable id) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Return the persistent instance of the given entity class
|
||||
* with the given identifier, throwing an exception if not found.
|
||||
* <p>Obtains the specified lock mode if the instance exists.
|
||||
* <p>This method is a thin wrapper around
|
||||
* {@link org.hibernate.Session#load(String, java.io.Serializable, LockMode)} for convenience.
|
||||
* For an explanation of the exact semantics of this method, please do refer to
|
||||
* the Hibernate API documentation in the first instance.
|
||||
* @param entityName the name of the persistent entity
|
||||
* @param id the identifier of the persistent instance
|
||||
* @param lockMode the lock mode to obtain
|
||||
* @return the persistent instance
|
||||
* @throws org.springframework.orm.ObjectRetrievalFailureException if not found
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#load(Class, java.io.Serializable)
|
||||
*/
|
||||
Object load(String entityName, Serializable id, LockMode lockMode) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Return all persistent instances of the given entity class.
|
||||
* Note: Use queries or criteria for retrieving a specific subset.
|
||||
* @param entityClass a persistent class
|
||||
* @return a {@link List} containing 0 or more persistent instances
|
||||
* @throws org.springframework.dao.DataAccessException if there is a Hibernate error
|
||||
* @see org.hibernate.Session#createCriteria
|
||||
*/
|
||||
<T> List<T> loadAll(Class<T> entityClass) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Load the persistent instance with the given identifier
|
||||
* into the given object, throwing an exception if not found.
|
||||
* <p>This method is a thin wrapper around
|
||||
* {@link org.hibernate.Session#load(Object, java.io.Serializable)} for convenience.
|
||||
* For an explanation of the exact semantics of this method, please do refer to
|
||||
* the Hibernate API documentation in the first instance.
|
||||
* @param entity the object (of the target class) to load into
|
||||
* @param id the identifier of the persistent instance
|
||||
* @throws org.springframework.orm.ObjectRetrievalFailureException if not found
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#load(Object, java.io.Serializable)
|
||||
*/
|
||||
void load(Object entity, Serializable id) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Re-read the state of the given persistent instance.
|
||||
* @param entity the persistent instance to re-read
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#refresh(Object)
|
||||
*/
|
||||
void refresh(Object entity) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Re-read the state of the given persistent instance.
|
||||
* Obtains the specified lock mode for the instance.
|
||||
* @param entity the persistent instance to re-read
|
||||
* @param lockMode the lock mode to obtain
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#refresh(Object, org.hibernate.LockMode)
|
||||
*/
|
||||
void refresh(Object entity, LockMode lockMode) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Check whether the given object is in the Session cache.
|
||||
* @param entity the persistence instance to check
|
||||
* @return whether the given object is in the Session cache
|
||||
* @throws org.springframework.dao.DataAccessException if there is a Hibernate error
|
||||
* @see org.hibernate.Session#contains
|
||||
*/
|
||||
boolean contains(Object entity) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Remove the given object from the {@link org.hibernate.Session} cache.
|
||||
* @param entity the persistent instance to evict
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#evict
|
||||
*/
|
||||
void evict(Object entity) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Force initialization of a Hibernate proxy or persistent collection.
|
||||
* @param proxy a proxy for a persistent object or a persistent collection
|
||||
* @throws DataAccessException if we can't initialize the proxy, for example
|
||||
* because it is not associated with an active Session
|
||||
* @see org.hibernate.Hibernate#initialize
|
||||
*/
|
||||
void initialize(Object proxy) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Return an enabled Hibernate {@link Filter} for the given filter name.
|
||||
* The returned {@code Filter} instance can be used to set filter parameters.
|
||||
* @param filterName the name of the filter
|
||||
* @return the enabled Hibernate {@code Filter} (either already
|
||||
* enabled or enabled on the fly by this operation)
|
||||
* @throws IllegalStateException if we are not running within a
|
||||
* transactional Session (in which case this operation does not make sense)
|
||||
*/
|
||||
Filter enableFilter(String filterName) throws IllegalStateException;
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Convenience methods for storing individual objects
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Obtain the specified lock level upon the given object, implicitly
|
||||
* checking whether the corresponding database entry still exists.
|
||||
* @param entity the persistent instance to lock
|
||||
* @param lockMode the lock mode to obtain
|
||||
* @throws org.springframework.orm.ObjectOptimisticLockingFailureException if not found
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#lock(Object, org.hibernate.LockMode)
|
||||
*/
|
||||
void lock(Object entity, LockMode lockMode) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Obtain the specified lock level upon the given object, implicitly
|
||||
* checking whether the corresponding database entry still exists.
|
||||
* @param entityName the name of the persistent entity
|
||||
* @param entity the persistent instance to lock
|
||||
* @param lockMode the lock mode to obtain
|
||||
* @throws org.springframework.orm.ObjectOptimisticLockingFailureException if not found
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#lock(String, Object, org.hibernate.LockMode)
|
||||
*/
|
||||
void lock(String entityName, Object entity, LockMode lockMode) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Persist the given transient instance.
|
||||
* @param entity the transient instance to persist
|
||||
* @return the generated identifier
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#save(Object)
|
||||
*/
|
||||
Serializable save(Object entity) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Persist the given transient instance.
|
||||
* @param entityName the name of the persistent entity
|
||||
* @param entity the transient instance to persist
|
||||
* @return the generated identifier
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#save(String, Object)
|
||||
*/
|
||||
Serializable save(String entityName, Object entity) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Update the given persistent instance,
|
||||
* associating it with the current Hibernate {@link org.hibernate.Session}.
|
||||
* @param entity the persistent instance to update
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#update(Object)
|
||||
*/
|
||||
void update(Object entity) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Update the given persistent instance,
|
||||
* associating it with the current Hibernate {@link org.hibernate.Session}.
|
||||
* <p>Obtains the specified lock mode if the instance exists, implicitly
|
||||
* checking whether the corresponding database entry still exists.
|
||||
* @param entity the persistent instance to update
|
||||
* @param lockMode the lock mode to obtain
|
||||
* @throws org.springframework.orm.ObjectOptimisticLockingFailureException if not found
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#update(Object)
|
||||
*/
|
||||
void update(Object entity, LockMode lockMode) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Update the given persistent instance,
|
||||
* associating it with the current Hibernate {@link org.hibernate.Session}.
|
||||
* @param entityName the name of the persistent entity
|
||||
* @param entity the persistent instance to update
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#update(String, Object)
|
||||
*/
|
||||
void update(String entityName, Object entity) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Update the given persistent instance,
|
||||
* associating it with the current Hibernate {@link org.hibernate.Session}.
|
||||
* <p>Obtains the specified lock mode if the instance exists, implicitly
|
||||
* checking whether the corresponding database entry still exists.
|
||||
* @param entityName the name of the persistent entity
|
||||
* @param entity the persistent instance to update
|
||||
* @param lockMode the lock mode to obtain
|
||||
* @throws org.springframework.orm.ObjectOptimisticLockingFailureException if not found
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#update(String, Object)
|
||||
*/
|
||||
void update(String entityName, Object entity, LockMode lockMode) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Save or update the given persistent instance,
|
||||
* according to its id (matching the configured "unsaved-value"?).
|
||||
* Associates the instance with the current Hibernate {@link org.hibernate.Session}.
|
||||
* @param entity the persistent instance to save or update
|
||||
* (to be associated with the Hibernate {@code Session})
|
||||
* @throws DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#saveOrUpdate(Object)
|
||||
*/
|
||||
void saveOrUpdate(Object entity) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Save or update the given persistent instance,
|
||||
* according to its id (matching the configured "unsaved-value"?).
|
||||
* Associates the instance with the current Hibernate {@code Session}.
|
||||
* @param entityName the name of the persistent entity
|
||||
* @param entity the persistent instance to save or update
|
||||
* (to be associated with the Hibernate {@code Session})
|
||||
* @throws DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#saveOrUpdate(String, Object)
|
||||
*/
|
||||
void saveOrUpdate(String entityName, Object entity) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Persist the state of the given detached instance according to the
|
||||
* given replication mode, reusing the current identifier value.
|
||||
* @param entity the persistent object to replicate
|
||||
* @param replicationMode the Hibernate ReplicationMode
|
||||
* @throws DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#replicate(Object, org.hibernate.ReplicationMode)
|
||||
*/
|
||||
void replicate(Object entity, ReplicationMode replicationMode) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Persist the state of the given detached instance according to the
|
||||
* given replication mode, reusing the current identifier value.
|
||||
* @param entityName the name of the persistent entity
|
||||
* @param entity the persistent object to replicate
|
||||
* @param replicationMode the Hibernate ReplicationMode
|
||||
* @throws DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#replicate(String, Object, org.hibernate.ReplicationMode)
|
||||
*/
|
||||
void replicate(String entityName, Object entity, ReplicationMode replicationMode) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Persist the given transient instance. Follows JSR-220 semantics.
|
||||
* <p>Similar to {@code save}, associating the given object
|
||||
* with the current Hibernate {@link org.hibernate.Session}.
|
||||
* @param entity the persistent instance to persist
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#persist(Object)
|
||||
* @see #save
|
||||
*/
|
||||
void persist(Object entity) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Persist the given transient instance. Follows JSR-220 semantics.
|
||||
* <p>Similar to {@code save}, associating the given object
|
||||
* with the current Hibernate {@link org.hibernate.Session}.
|
||||
* @param entityName the name of the persistent entity
|
||||
* @param entity the persistent instance to persist
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#persist(String, Object)
|
||||
* @see #save
|
||||
*/
|
||||
void persist(String entityName, Object entity) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Copy the state of the given object onto the persistent object
|
||||
* with the same identifier. Follows JSR-220 semantics.
|
||||
* <p>Similar to {@code saveOrUpdate}, but never associates the given
|
||||
* object with the current Hibernate Session. In case of a new entity,
|
||||
* the state will be copied over as well.
|
||||
* <p>Note that {@code merge} will <i>not</i> update the identifiers
|
||||
* in the passed-in object graph (in contrast to TopLink)! Consider
|
||||
* registering Spring's {@code IdTransferringMergeEventListener} if
|
||||
* you would like to have newly assigned ids transferred to the original
|
||||
* object graph too.
|
||||
* @param entity the object to merge with the corresponding persistence instance
|
||||
* @return the updated, registered persistent instance
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#merge(Object)
|
||||
* @see #saveOrUpdate
|
||||
*/
|
||||
<T> T merge(T entity) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Copy the state of the given object onto the persistent object
|
||||
* with the same identifier. Follows JSR-220 semantics.
|
||||
* <p>Similar to {@code saveOrUpdate}, but never associates the given
|
||||
* object with the current Hibernate {@link org.hibernate.Session}. In
|
||||
* the case of a new entity, the state will be copied over as well.
|
||||
* <p>Note that {@code merge} will <i>not</i> update the identifiers
|
||||
* in the passed-in object graph (in contrast to TopLink)! Consider
|
||||
* registering Spring's {@code IdTransferringMergeEventListener}
|
||||
* if you would like to have newly assigned ids transferred to the
|
||||
* original object graph too.
|
||||
* @param entityName the name of the persistent entity
|
||||
* @param entity the object to merge with the corresponding persistence instance
|
||||
* @return the updated, registered persistent instance
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#merge(String, Object)
|
||||
* @see #saveOrUpdate
|
||||
*/
|
||||
<T> T merge(String entityName, T entity) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Delete the given persistent instance.
|
||||
* @param entity the persistent instance to delete
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#delete(Object)
|
||||
*/
|
||||
void delete(Object entity) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Delete the given persistent instance.
|
||||
* <p>Obtains the specified lock mode if the instance exists, implicitly
|
||||
* checking whether the corresponding database entry still exists.
|
||||
* @param entity the persistent instance to delete
|
||||
* @param lockMode the lock mode to obtain
|
||||
* @throws org.springframework.orm.ObjectOptimisticLockingFailureException if not found
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#delete(Object)
|
||||
*/
|
||||
void delete(Object entity, LockMode lockMode) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Delete the given persistent instance.
|
||||
* @param entityName the name of the persistent entity
|
||||
* @param entity the persistent instance to delete
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#delete(Object)
|
||||
*/
|
||||
void delete(String entityName, Object entity) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Delete the given persistent instance.
|
||||
* <p>Obtains the specified lock mode if the instance exists, implicitly
|
||||
* checking whether the corresponding database entry still exists.
|
||||
* @param entityName the name of the persistent entity
|
||||
* @param entity the persistent instance to delete
|
||||
* @param lockMode the lock mode to obtain
|
||||
* @throws org.springframework.orm.ObjectOptimisticLockingFailureException if not found
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#delete(Object)
|
||||
*/
|
||||
void delete(String entityName, Object entity, LockMode lockMode) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Delete all given persistent instances.
|
||||
* <p>This can be combined with any of the find methods to delete by query
|
||||
* in two lines of code.
|
||||
* @param entities the persistent instances to delete
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#delete(Object)
|
||||
*/
|
||||
void deleteAll(Collection<?> entities) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Flush all pending saves, updates and deletes to the database.
|
||||
* <p>Only invoke this for selective eager flushing, for example when
|
||||
* JDBC code needs to see certain changes within the same transaction.
|
||||
* Else, it is preferable to rely on auto-flushing at transaction
|
||||
* completion.
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#flush
|
||||
*/
|
||||
void flush() throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Remove all objects from the {@link org.hibernate.Session} cache, and
|
||||
* cancel all pending saves, updates and deletes.
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#clear
|
||||
*/
|
||||
void clear() throws DataAccessException;
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Convenience finder methods for HQL strings
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Execute an HQL query, binding a number of values to "?" parameters
|
||||
* in the query string.
|
||||
* @param queryString a query expressed in Hibernate's query language
|
||||
* @param values the values of the parameters
|
||||
* @return a {@link List} containing the results of the query execution
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#createQuery
|
||||
*/
|
||||
List<?> find(String queryString, Object... values) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Execute an HQL query, binding one value to a ":" named parameter
|
||||
* in the query string.
|
||||
* @param queryString a query expressed in Hibernate's query language
|
||||
* @param paramName the name of the parameter
|
||||
* @param value the value of the parameter
|
||||
* @return a {@link List} containing the results of the query execution
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#getNamedQuery(String)
|
||||
*/
|
||||
List<?> findByNamedParam(String queryString, String paramName, Object value) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Execute an HQL query, binding a number of values to ":" named
|
||||
* parameters in the query string.
|
||||
* @param queryString a query expressed in Hibernate's query language
|
||||
* @param paramNames the names of the parameters
|
||||
* @param values the values of the parameters
|
||||
* @return a {@link List} containing the results of the query execution
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#getNamedQuery(String)
|
||||
*/
|
||||
List<?> findByNamedParam(String queryString, String[] paramNames, Object[] values) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Execute an HQL query, binding the properties of the given bean to
|
||||
* <i>named</i> parameters in the query string.
|
||||
* @param queryString a query expressed in Hibernate's query language
|
||||
* @param valueBean the values of the parameters
|
||||
* @return a {@link List} containing the results of the query execution
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Query#setProperties
|
||||
* @see org.hibernate.Session#createQuery
|
||||
*/
|
||||
List<?> findByValueBean(String queryString, Object valueBean) throws DataAccessException;
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Convenience finder methods for named queries
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Execute a named query binding a number of values to "?" parameters
|
||||
* in the query string.
|
||||
* <p>A named query is defined in a Hibernate mapping file.
|
||||
* @param queryName the name of a Hibernate query in a mapping file
|
||||
* @param values the values of the parameters
|
||||
* @return a {@link List} containing the results of the query execution
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#getNamedQuery(String)
|
||||
*/
|
||||
List<?> findByNamedQuery(String queryName, Object... values) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Execute a named query, binding one value to a ":" named parameter
|
||||
* in the query string.
|
||||
* <p>A named query is defined in a Hibernate mapping file.
|
||||
* @param queryName the name of a Hibernate query in a mapping file
|
||||
* @param paramName the name of parameter
|
||||
* @param value the value of the parameter
|
||||
* @return a {@link List} containing the results of the query execution
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#getNamedQuery(String)
|
||||
*/
|
||||
List<?> findByNamedQueryAndNamedParam(String queryName, String paramName, Object value)
|
||||
throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Execute a named query, binding a number of values to ":" named
|
||||
* parameters in the query string.
|
||||
* <p>A named query is defined in a Hibernate mapping file.
|
||||
* @param queryName the name of a Hibernate query in a mapping file
|
||||
* @param paramNames the names of the parameters
|
||||
* @param values the values of the parameters
|
||||
* @return a {@link List} containing the results of the query execution
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#getNamedQuery(String)
|
||||
*/
|
||||
List<?> findByNamedQueryAndNamedParam(String queryName, String[] paramNames, Object[] values)
|
||||
throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Execute a named query, binding the properties of the given bean to
|
||||
* ":" named parameters in the query string.
|
||||
* <p>A named query is defined in a Hibernate mapping file.
|
||||
* @param queryName the name of a Hibernate query in a mapping file
|
||||
* @param valueBean the values of the parameters
|
||||
* @return a {@link List} containing the results of the query execution
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Query#setProperties
|
||||
* @see org.hibernate.Session#getNamedQuery(String)
|
||||
*/
|
||||
List<?> findByNamedQueryAndValueBean(String queryName, Object valueBean) throws DataAccessException;
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Convenience finder methods for detached criteria
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Execute a query based on a given Hibernate criteria object.
|
||||
* @param criteria the detached Hibernate criteria object.
|
||||
* <b>Note: Do not reuse criteria objects! They need to recreated per execution,
|
||||
* due to the suboptimal design of Hibernate's criteria facility.</b>
|
||||
* @return a {@link List} containing 0 or more persistent instances
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.criterion.DetachedCriteria#getExecutableCriteria(org.hibernate.Session)
|
||||
*/
|
||||
List<?> findByCriteria(DetachedCriteria criteria) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Execute a query based on the given Hibernate criteria object.
|
||||
* @param criteria the detached Hibernate criteria object.
|
||||
* <b>Note: Do not reuse criteria objects! They need to recreated per execution,
|
||||
* due to the suboptimal design of Hibernate's criteria facility.</b>
|
||||
* @param firstResult the index of the first result object to be retrieved
|
||||
* (numbered from 0)
|
||||
* @param maxResults the maximum number of result objects to retrieve
|
||||
* (or <=0 for no limit)
|
||||
* @return a {@link List} containing 0 or more persistent instances
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.criterion.DetachedCriteria#getExecutableCriteria(org.hibernate.Session)
|
||||
* @see org.hibernate.Criteria#setFirstResult(int)
|
||||
* @see org.hibernate.Criteria#setMaxResults(int)
|
||||
*/
|
||||
List<?> findByCriteria(DetachedCriteria criteria, int firstResult, int maxResults) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Execute a query based on the given example entity object.
|
||||
* @param exampleEntity an instance of the desired entity,
|
||||
* serving as example for "query-by-example"
|
||||
* @return a {@link List} containing 0 or more persistent instances
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.criterion.Example#create(Object)
|
||||
*/
|
||||
<T> List<T> findByExample(T exampleEntity) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Execute a query based on the given example entity object.
|
||||
* @param entityName the name of the persistent entity
|
||||
* @param exampleEntity an instance of the desired entity,
|
||||
* serving as example for "query-by-example"
|
||||
* @return a {@link List} containing 0 or more persistent instances
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.criterion.Example#create(Object)
|
||||
*/
|
||||
<T> List<T> findByExample(String entityName, T exampleEntity) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Execute a query based on a given example entity object.
|
||||
* @param exampleEntity an instance of the desired entity,
|
||||
* serving as example for "query-by-example"
|
||||
* @param firstResult the index of the first result object to be retrieved
|
||||
* (numbered from 0)
|
||||
* @param maxResults the maximum number of result objects to retrieve
|
||||
* (or <=0 for no limit)
|
||||
* @return a {@link List} containing 0 or more persistent instances
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.criterion.Example#create(Object)
|
||||
* @see org.hibernate.Criteria#setFirstResult(int)
|
||||
* @see org.hibernate.Criteria#setMaxResults(int)
|
||||
*/
|
||||
<T> List<T> findByExample(T exampleEntity, int firstResult, int maxResults) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Execute a query based on a given example entity object.
|
||||
* @param entityName the name of the persistent entity
|
||||
* @param exampleEntity an instance of the desired entity,
|
||||
* serving as example for "query-by-example"
|
||||
* @param firstResult the index of the first result object to be retrieved
|
||||
* (numbered from 0)
|
||||
* @param maxResults the maximum number of result objects to retrieve
|
||||
* (or <=0 for no limit)
|
||||
* @return a {@link List} containing 0 or more persistent instances
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.criterion.Example#create(Object)
|
||||
* @see org.hibernate.Criteria#setFirstResult(int)
|
||||
* @see org.hibernate.Criteria#setMaxResults(int)
|
||||
*/
|
||||
<T> List<T> findByExample(String entityName, T exampleEntity, int firstResult, int maxResults)
|
||||
throws DataAccessException;
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Convenience query methods for iteration and bulk updates/deletes
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Execute a query for persistent instances, binding a number of
|
||||
* values to "?" parameters in the query string.
|
||||
* <p>Returns the results as an {@link Iterator}. Entities returned are
|
||||
* initialized on demand. See the Hibernate API documentation for details.
|
||||
* @param queryString a query expressed in Hibernate's query language
|
||||
* @param values the values of the parameters
|
||||
* @return an {@link Iterator} containing 0 or more persistent instances
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#createQuery
|
||||
* @see org.hibernate.Query#iterate
|
||||
*/
|
||||
Iterator<?> iterate(String queryString, Object... values) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Immediately close an {@link Iterator} created by any of the various
|
||||
* {@code iterate(..)} operations, instead of waiting until the
|
||||
* session is closed or disconnected.
|
||||
* @param it the {@code Iterator} to close
|
||||
* @throws DataAccessException if the {@code Iterator} could not be closed
|
||||
* @see org.hibernate.Hibernate#close
|
||||
*/
|
||||
void closeIterator(Iterator<?> it) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Update/delete all objects according to the given query, binding a number of
|
||||
* values to "?" parameters in the query string.
|
||||
* @param queryString an update/delete query expressed in Hibernate's query language
|
||||
* @param values the values of the parameters
|
||||
* @return the number of instances updated/deleted
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#createQuery
|
||||
* @see org.hibernate.Query#executeUpdate
|
||||
*/
|
||||
int bulkUpdate(String queryString, Object... values) throws DataAccessException;
|
||||
|
||||
}
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate4;
|
||||
|
||||
import org.hibernate.StaleObjectStateException;
|
||||
import org.hibernate.StaleStateException;
|
||||
import org.hibernate.dialect.lock.OptimisticEntityLockException;
|
||||
|
||||
import org.springframework.orm.ObjectOptimisticLockingFailureException;
|
||||
|
||||
/**
|
||||
* Hibernate-specific subclass of ObjectOptimisticLockingFailureException.
|
||||
* Converts Hibernate's StaleObjectStateException, StaleStateException
|
||||
* and OptimisticEntityLockException.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.1
|
||||
* @see SessionFactoryUtils#convertHibernateAccessException
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class HibernateOptimisticLockingFailureException extends ObjectOptimisticLockingFailureException {
|
||||
|
||||
public HibernateOptimisticLockingFailureException(StaleObjectStateException ex) {
|
||||
super(ex.getEntityName(), ex.getIdentifier(), ex);
|
||||
}
|
||||
|
||||
public HibernateOptimisticLockingFailureException(StaleStateException ex) {
|
||||
super(ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
public HibernateOptimisticLockingFailureException(OptimisticEntityLockException ex) {
|
||||
super(ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate4;
|
||||
|
||||
import org.hibernate.QueryException;
|
||||
|
||||
import org.springframework.dao.InvalidDataAccessResourceUsageException;
|
||||
|
||||
/**
|
||||
* Hibernate-specific subclass of InvalidDataAccessResourceUsageException,
|
||||
* thrown on invalid HQL query syntax.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.1
|
||||
* @see SessionFactoryUtils#convertHibernateAccessException
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class HibernateQueryException extends InvalidDataAccessResourceUsageException {
|
||||
|
||||
public HibernateQueryException(QueryException ex) {
|
||||
super(ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the HQL query string that was invalid.
|
||||
*/
|
||||
public String getQueryString() {
|
||||
return ((QueryException) getCause()).getQueryString();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate4;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
|
||||
import org.springframework.dao.UncategorizedDataAccessException;
|
||||
|
||||
/**
|
||||
* Hibernate-specific subclass of UncategorizedDataAccessException,
|
||||
* for Hibernate system errors that do not match any concrete
|
||||
* {@code org.springframework.dao} exceptions.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.1
|
||||
* @see SessionFactoryUtils#convertHibernateAccessException
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class HibernateSystemException extends UncategorizedDataAccessException {
|
||||
|
||||
/**
|
||||
* Create a new HibernateSystemException,
|
||||
* wrapping an arbitrary HibernateException.
|
||||
* @param cause the HibernateException thrown
|
||||
*/
|
||||
public HibernateSystemException(HibernateException cause) {
|
||||
super(cause != null ? cause.getMessage() : null, cause);
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,843 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate4;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.ResultSet;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.hibernate.ConnectionReleaseMode;
|
||||
import org.hibernate.FlushMode;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.Interceptor;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.Transaction;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.engine.transaction.spi.TransactionContext;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.DataAccessResourceFailureException;
|
||||
import org.springframework.jdbc.datasource.ConnectionHolder;
|
||||
import org.springframework.jdbc.datasource.DataSourceUtils;
|
||||
import org.springframework.jdbc.datasource.JdbcTransactionObjectSupport;
|
||||
import org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy;
|
||||
import org.springframework.transaction.CannotCreateTransactionException;
|
||||
import org.springframework.transaction.IllegalTransactionStateException;
|
||||
import org.springframework.transaction.InvalidIsolationLevelException;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.TransactionSystemException;
|
||||
import org.springframework.transaction.support.AbstractPlatformTransactionManager;
|
||||
import org.springframework.transaction.support.DefaultTransactionStatus;
|
||||
import org.springframework.transaction.support.ResourceTransactionManager;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.transaction.PlatformTransactionManager}
|
||||
* implementation for a single Hibernate {@link org.hibernate.SessionFactory}.
|
||||
* Binds a Hibernate Session from the specified factory to the thread,
|
||||
* potentially allowing for one thread-bound Session per factory.
|
||||
* {@code SessionFactory.getCurrentSession()} is required for Hibernate
|
||||
* access code that needs to support this transaction handling mechanism,
|
||||
* with the SessionFactory being configured with {@link SpringSessionContext}.
|
||||
*
|
||||
* <p>Supports custom isolation levels, and timeouts that get applied as
|
||||
* Hibernate transaction timeouts.
|
||||
*
|
||||
* <p>This transaction manager is appropriate for applications that use a single
|
||||
* Hibernate SessionFactory for transactional data access, but it also supports
|
||||
* direct DataSource access within a transaction (i.e. plain JDBC code working
|
||||
* with the same DataSource). This allows for mixing services which access Hibernate
|
||||
* and services which use plain JDBC (without being aware of Hibernate)!
|
||||
* Application code needs to stick to the same simple Connection lookup pattern as
|
||||
* with {@link org.springframework.jdbc.datasource.DataSourceTransactionManager}
|
||||
* (i.e. {@link org.springframework.jdbc.datasource.DataSourceUtils#getConnection}
|
||||
* or going through a
|
||||
* {@link org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy}).
|
||||
*
|
||||
* <p>Note: To be able to register a DataSource's Connection for plain JDBC code,
|
||||
* this instance needs to be aware of the DataSource ({@link #setDataSource}).
|
||||
* The given DataSource should obviously match the one used by the given SessionFactory.
|
||||
*
|
||||
* <p>JTA (usually through {@link org.springframework.transaction.jta.JtaTransactionManager})
|
||||
* is necessary for accessing multiple transactional resources within the same
|
||||
* transaction. The DataSource that Hibernate uses needs to be JTA-enabled in
|
||||
* such a scenario (see container setup).
|
||||
*
|
||||
* <p>This transaction manager supports nested transactions via JDBC 3.0 Savepoints.
|
||||
* The {@link #setNestedTransactionAllowed} "nestedTransactionAllowed"} flag defaults
|
||||
* to "false", though, as nested transactions will just apply to the JDBC Connection,
|
||||
* not to the Hibernate Session and its cached entity objects and related context.
|
||||
* You can manually set the flag to "true" if you want to use nested transactions
|
||||
* for JDBC access code which participates in Hibernate transactions (provided that
|
||||
* your JDBC driver supports Savepoints). <i>Note that Hibernate itself does not
|
||||
* support nested transactions! Hence, do not expect Hibernate access code to
|
||||
* semantically participate in a nested transaction.</i>
|
||||
*
|
||||
* <p><b>NOTE: Hibernate 4.2+ is strongly recommended for efficient transaction
|
||||
* management with Spring, in particular for transactional Spring JDBC access.</b>
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.1
|
||||
* @see #setSessionFactory
|
||||
* @see #setDataSource
|
||||
* @see org.hibernate.SessionFactory#getCurrentSession()
|
||||
* @see org.springframework.jdbc.datasource.DataSourceUtils#getConnection
|
||||
* @see org.springframework.jdbc.datasource.DataSourceUtils#releaseConnection
|
||||
* @see org.springframework.jdbc.core.JdbcTemplate
|
||||
* @see org.springframework.jdbc.datasource.DataSourceTransactionManager
|
||||
* @see org.springframework.transaction.jta.JtaTransactionManager
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class HibernateTransactionManager extends AbstractPlatformTransactionManager
|
||||
implements ResourceTransactionManager, BeanFactoryAware, InitializingBean {
|
||||
|
||||
private SessionFactory sessionFactory;
|
||||
|
||||
private DataSource dataSource;
|
||||
|
||||
private boolean autodetectDataSource = true;
|
||||
|
||||
private boolean prepareConnection = true;
|
||||
|
||||
private boolean allowResultAccessAfterCompletion = false;
|
||||
|
||||
private boolean hibernateManagedSession = false;
|
||||
|
||||
private Object entityInterceptor;
|
||||
|
||||
/**
|
||||
* Just needed for entityInterceptorBeanName.
|
||||
* @see #setEntityInterceptorBeanName
|
||||
*/
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new HibernateTransactionManager instance.
|
||||
* A SessionFactory has to be set to be able to use it.
|
||||
* @see #setSessionFactory
|
||||
*/
|
||||
public HibernateTransactionManager() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new HibernateTransactionManager instance.
|
||||
* @param sessionFactory SessionFactory to manage transactions for
|
||||
*/
|
||||
public HibernateTransactionManager(SessionFactory sessionFactory) {
|
||||
this.sessionFactory = sessionFactory;
|
||||
afterPropertiesSet();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the SessionFactory that this instance should manage transactions for.
|
||||
*/
|
||||
public void setSessionFactory(SessionFactory sessionFactory) {
|
||||
this.sessionFactory = sessionFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the SessionFactory that this instance should manage transactions for.
|
||||
*/
|
||||
public SessionFactory getSessionFactory() {
|
||||
return this.sessionFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the JDBC DataSource that this instance should manage transactions for.
|
||||
* The DataSource should match the one used by the Hibernate SessionFactory:
|
||||
* for example, you could specify the same JNDI DataSource for both.
|
||||
* <p>If the SessionFactory was configured with LocalDataSourceConnectionProvider,
|
||||
* i.e. by Spring's LocalSessionFactoryBean with a specified "dataSource",
|
||||
* the DataSource will be auto-detected: You can still explicitly specify the
|
||||
* DataSource, but you don't need to in this case.
|
||||
* <p>A transactional JDBC Connection for this DataSource will be provided to
|
||||
* application code accessing this DataSource directly via DataSourceUtils
|
||||
* or JdbcTemplate. The Connection will be taken from the Hibernate Session.
|
||||
* <p>The DataSource specified here should be the target DataSource to manage
|
||||
* transactions for, not a TransactionAwareDataSourceProxy. Only data access
|
||||
* code may work with TransactionAwareDataSourceProxy, while the transaction
|
||||
* manager needs to work on the underlying target DataSource. If there's
|
||||
* nevertheless a TransactionAwareDataSourceProxy passed in, it will be
|
||||
* unwrapped to extract its target DataSource.
|
||||
* @see #setAutodetectDataSource
|
||||
* @see org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy
|
||||
* @see org.springframework.jdbc.datasource.DataSourceUtils
|
||||
* @see org.springframework.jdbc.core.JdbcTemplate
|
||||
*/
|
||||
public void setDataSource(DataSource dataSource) {
|
||||
if (dataSource instanceof TransactionAwareDataSourceProxy) {
|
||||
// If we got a TransactionAwareDataSourceProxy, we need to perform transactions
|
||||
// for its underlying target DataSource, else data access code won't see
|
||||
// properly exposed transactions (i.e. transactions for the target DataSource).
|
||||
this.dataSource = ((TransactionAwareDataSourceProxy) dataSource).getTargetDataSource();
|
||||
}
|
||||
else {
|
||||
this.dataSource = dataSource;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the JDBC DataSource that this instance manages transactions for.
|
||||
*/
|
||||
public DataSource getDataSource() {
|
||||
return this.dataSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether to autodetect a JDBC DataSource used by the Hibernate SessionFactory,
|
||||
* if set via LocalSessionFactoryBean's {@code setDataSource}. Default is "true".
|
||||
* <p>Can be turned off to deliberately ignore an available DataSource, in order
|
||||
* to not expose Hibernate transactions as JDBC transactions for that DataSource.
|
||||
* @see #setDataSource
|
||||
*/
|
||||
public void setAutodetectDataSource(boolean autodetectDataSource) {
|
||||
this.autodetectDataSource = autodetectDataSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether to prepare the underlying JDBC Connection of a transactional
|
||||
* Hibernate Session, that is, whether to apply a transaction-specific
|
||||
* isolation level and/or the transaction's read-only flag to the underlying
|
||||
* JDBC Connection.
|
||||
* <p>Default is "true". If you turn this flag off, the transaction manager
|
||||
* will not support per-transaction isolation levels anymore. It will not
|
||||
* call {@code Connection.setReadOnly(true)} for read-only transactions
|
||||
* anymore either. If this flag is turned off, no cleanup of a JDBC Connection
|
||||
* is required after a transaction, since no Connection settings will get modified.
|
||||
* @see java.sql.Connection#setTransactionIsolation
|
||||
* @see java.sql.Connection#setReadOnly
|
||||
*/
|
||||
public void setPrepareConnection(boolean prepareConnection) {
|
||||
this.prepareConnection = prepareConnection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether to allow result access after completion, typically via Hibernate's
|
||||
* ScrollableResults mechanism.
|
||||
* <p>Default is "false". Turning this flag on enforces over-commit holdability on the
|
||||
* underlying JDBC Connection (if {@link #prepareConnection "prepareConnection"} is on)
|
||||
* and skips the disconnect-on-completion step.
|
||||
* @since 4.1.2
|
||||
* @see java.sql.Connection#setHoldability
|
||||
* @see ResultSet#HOLD_CURSORS_OVER_COMMIT
|
||||
* @see #disconnectOnCompletion(Session)
|
||||
*/
|
||||
public void setAllowResultAccessAfterCompletion(boolean allowResultAccessAfterCompletion) {
|
||||
this.allowResultAccessAfterCompletion = allowResultAccessAfterCompletion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether to operate on a Hibernate-managed Session instead of a
|
||||
* Spring-managed Session, that is, whether to obtain the Session through
|
||||
* Hibernate's {@link org.hibernate.SessionFactory#getCurrentSession()}
|
||||
* instead of {@link org.hibernate.SessionFactory#openSession()} (with a Spring
|
||||
* {@link org.springframework.transaction.support.TransactionSynchronizationManager}
|
||||
* check preceding it).
|
||||
* <p>Default is "false", i.e. using a Spring-managed Session: taking the current
|
||||
* thread-bound Session if available (e.g. in an Open-Session-in-View scenario),
|
||||
* creating a new Session for the current transaction otherwise.
|
||||
* <p>Switch this flag to "true" in order to enforce use of a Hibernate-managed Session.
|
||||
* Note that this requires {@link org.hibernate.SessionFactory#getCurrentSession()}
|
||||
* to always return a proper Session when called for a Spring-managed transaction;
|
||||
* transaction begin will fail if the {@code getCurrentSession()} call fails.
|
||||
* <p>This mode will typically be used in combination with a custom Hibernate
|
||||
* {@link org.hibernate.context.spi.CurrentSessionContext} implementation that stores
|
||||
* Sessions in a place other than Spring's TransactionSynchronizationManager.
|
||||
* It may also be used in combination with Spring's Open-Session-in-View support
|
||||
* (using Spring's default {@link SpringSessionContext}), in which case it subtly
|
||||
* differs from the Spring-managed Session mode: The pre-bound Session will <i>not</i>
|
||||
* receive a {@code clear()} call (on rollback) or a {@code disconnect()}
|
||||
* call (on transaction completion) in such a scenario; this is rather left up
|
||||
* to a custom CurrentSessionContext implementation (if desired).
|
||||
*/
|
||||
public void setHibernateManagedSession(boolean hibernateManagedSession) {
|
||||
this.hibernateManagedSession = hibernateManagedSession;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the bean name of a Hibernate entity interceptor that allows to inspect
|
||||
* and change property values before writing to and reading from the database.
|
||||
* Will get applied to any new Session created by this transaction manager.
|
||||
* <p>Requires the bean factory to be known, to be able to resolve the bean
|
||||
* name to an interceptor instance on session creation. Typically used for
|
||||
* prototype interceptors, i.e. a new interceptor instance per session.
|
||||
* <p>Can also be used for shared interceptor instances, but it is recommended
|
||||
* to set the interceptor reference directly in such a scenario.
|
||||
* @param entityInterceptorBeanName the name of the entity interceptor in
|
||||
* the bean factory
|
||||
* @see #setBeanFactory
|
||||
* @see #setEntityInterceptor
|
||||
*/
|
||||
public void setEntityInterceptorBeanName(String entityInterceptorBeanName) {
|
||||
this.entityInterceptor = entityInterceptorBeanName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a Hibernate entity interceptor that allows to inspect and change
|
||||
* property values before writing to and reading from the database.
|
||||
* Will get applied to any new Session created by this transaction manager.
|
||||
* <p>Such an interceptor can either be set at the SessionFactory level,
|
||||
* i.e. on LocalSessionFactoryBean, or at the Session level, i.e. on
|
||||
* HibernateTransactionManager.
|
||||
* @see LocalSessionFactoryBean#setEntityInterceptor
|
||||
*/
|
||||
public void setEntityInterceptor(Interceptor entityInterceptor) {
|
||||
this.entityInterceptor = entityInterceptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current Hibernate entity interceptor, or {@code null} if none.
|
||||
* Resolves an entity interceptor bean name via the bean factory,
|
||||
* if necessary.
|
||||
* @throws IllegalStateException if bean name specified but no bean factory set
|
||||
* @throws BeansException if bean name resolution via the bean factory failed
|
||||
* @see #setEntityInterceptor
|
||||
* @see #setEntityInterceptorBeanName
|
||||
* @see #setBeanFactory
|
||||
*/
|
||||
public Interceptor getEntityInterceptor() throws IllegalStateException, BeansException {
|
||||
if (this.entityInterceptor instanceof Interceptor) {
|
||||
return (Interceptor) entityInterceptor;
|
||||
}
|
||||
else if (this.entityInterceptor instanceof String) {
|
||||
if (this.beanFactory == null) {
|
||||
throw new IllegalStateException("Cannot get entity interceptor via bean name if no bean factory set");
|
||||
}
|
||||
String beanName = (String) this.entityInterceptor;
|
||||
return this.beanFactory.getBean(beanName, Interceptor.class);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The bean factory just needs to be known for resolving entity interceptor
|
||||
* bean names. It does not need to be set for any other mode of operation.
|
||||
* @see #setEntityInterceptorBeanName
|
||||
*/
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
if (getSessionFactory() == null) {
|
||||
throw new IllegalArgumentException("Property 'sessionFactory' is required");
|
||||
}
|
||||
if (this.entityInterceptor instanceof String && this.beanFactory == null) {
|
||||
throw new IllegalArgumentException("Property 'beanFactory' is required for 'entityInterceptorBeanName'");
|
||||
}
|
||||
|
||||
// Check for SessionFactory's DataSource.
|
||||
if (this.autodetectDataSource && getDataSource() == null) {
|
||||
DataSource sfds = SessionFactoryUtils.getDataSource(getSessionFactory());
|
||||
if (sfds != null) {
|
||||
// Use the SessionFactory's DataSource for exposing transactions to JDBC code.
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Using DataSource [" + sfds +
|
||||
"] of Hibernate SessionFactory for HibernateTransactionManager");
|
||||
}
|
||||
setDataSource(sfds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object getResourceFactory() {
|
||||
return getSessionFactory();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object doGetTransaction() {
|
||||
HibernateTransactionObject txObject = new HibernateTransactionObject();
|
||||
txObject.setSavepointAllowed(isNestedTransactionAllowed());
|
||||
|
||||
SessionHolder sessionHolder =
|
||||
(SessionHolder) TransactionSynchronizationManager.getResource(getSessionFactory());
|
||||
if (sessionHolder != null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Found thread-bound Session [" + sessionHolder.getSession() + "] for Hibernate transaction");
|
||||
}
|
||||
txObject.setSessionHolder(sessionHolder);
|
||||
}
|
||||
else if (this.hibernateManagedSession) {
|
||||
try {
|
||||
Session session = this.sessionFactory.getCurrentSession();
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Found Hibernate-managed Session [" + session + "] for Spring-managed transaction");
|
||||
}
|
||||
txObject.setExistingSession(session);
|
||||
}
|
||||
catch (HibernateException ex) {
|
||||
throw new DataAccessResourceFailureException(
|
||||
"Could not obtain Hibernate-managed Session for Spring-managed transaction", ex);
|
||||
}
|
||||
}
|
||||
|
||||
if (getDataSource() != null) {
|
||||
ConnectionHolder conHolder = (ConnectionHolder)
|
||||
TransactionSynchronizationManager.getResource(getDataSource());
|
||||
txObject.setConnectionHolder(conHolder);
|
||||
}
|
||||
|
||||
return txObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isExistingTransaction(Object transaction) {
|
||||
HibernateTransactionObject txObject = (HibernateTransactionObject) transaction;
|
||||
return (txObject.hasSpringManagedTransaction() ||
|
||||
(this.hibernateManagedSession && txObject.hasHibernateManagedTransaction()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doBegin(Object transaction, TransactionDefinition definition) {
|
||||
HibernateTransactionObject txObject = (HibernateTransactionObject) transaction;
|
||||
|
||||
if (txObject.hasConnectionHolder() && !txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
|
||||
throw new IllegalTransactionStateException(
|
||||
"Pre-bound JDBC Connection found! HibernateTransactionManager does not support " +
|
||||
"running within DataSourceTransactionManager if told to manage the DataSource itself. " +
|
||||
"It is recommended to use a single HibernateTransactionManager for all transactions " +
|
||||
"on a single DataSource, no matter whether Hibernate or JDBC access.");
|
||||
}
|
||||
|
||||
Session session = null;
|
||||
|
||||
try {
|
||||
if (txObject.getSessionHolder() == null || txObject.getSessionHolder().isSynchronizedWithTransaction()) {
|
||||
Interceptor entityInterceptor = getEntityInterceptor();
|
||||
Session newSession = (entityInterceptor != null ?
|
||||
getSessionFactory().withOptions().interceptor(entityInterceptor).openSession() :
|
||||
getSessionFactory().openSession());
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Opened new Session [" + newSession + "] for Hibernate transaction");
|
||||
}
|
||||
txObject.setSession(newSession);
|
||||
}
|
||||
|
||||
session = txObject.getSessionHolder().getSession();
|
||||
|
||||
if (this.prepareConnection && isSameConnectionForEntireSession(session)) {
|
||||
// We're allowed to change the transaction settings of the JDBC Connection.
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Preparing JDBC Connection of Hibernate Session [" + session + "]");
|
||||
}
|
||||
Connection con = ((SessionImplementor) session).connection();
|
||||
Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
|
||||
txObject.setPreviousIsolationLevel(previousIsolationLevel);
|
||||
if (this.allowResultAccessAfterCompletion && !txObject.isNewSession()) {
|
||||
int currentHoldability = con.getHoldability();
|
||||
if (currentHoldability != ResultSet.HOLD_CURSORS_OVER_COMMIT) {
|
||||
txObject.setPreviousHoldability(currentHoldability);
|
||||
con.setHoldability(ResultSet.HOLD_CURSORS_OVER_COMMIT);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Not allowed to change the transaction settings of the JDBC Connection.
|
||||
if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) {
|
||||
// We should set a specific isolation level but are not allowed to...
|
||||
throw new InvalidIsolationLevelException(
|
||||
"HibernateTransactionManager is not allowed to support custom isolation levels: " +
|
||||
"make sure that its 'prepareConnection' flag is on (the default) and that the " +
|
||||
"Hibernate connection release mode is set to 'on_close' (the default for JDBC).");
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Not preparing JDBC Connection of Hibernate Session [" + session + "]");
|
||||
}
|
||||
}
|
||||
|
||||
if (definition.isReadOnly() && txObject.isNewSession()) {
|
||||
// Just set to MANUAL in case of a new Session for this transaction.
|
||||
session.setFlushMode(FlushMode.MANUAL);
|
||||
}
|
||||
|
||||
if (!definition.isReadOnly() && !txObject.isNewSession()) {
|
||||
// We need AUTO or COMMIT for a non-read-only transaction.
|
||||
FlushMode flushMode = session.getFlushMode();
|
||||
if (FlushMode.MANUAL.equals(flushMode)) {
|
||||
session.setFlushMode(FlushMode.AUTO);
|
||||
txObject.getSessionHolder().setPreviousFlushMode(flushMode);
|
||||
}
|
||||
}
|
||||
|
||||
Transaction hibTx;
|
||||
|
||||
// Register transaction timeout.
|
||||
int timeout = determineTimeout(definition);
|
||||
if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
|
||||
// Use Hibernate's own transaction timeout mechanism on Hibernate 3.1+
|
||||
// Applies to all statements, also to inserts, updates and deletes!
|
||||
hibTx = session.getTransaction();
|
||||
hibTx.setTimeout(timeout);
|
||||
hibTx.begin();
|
||||
}
|
||||
else {
|
||||
// Open a plain Hibernate transaction without specified timeout.
|
||||
hibTx = session.beginTransaction();
|
||||
}
|
||||
|
||||
// Add the Hibernate transaction to the session holder.
|
||||
txObject.getSessionHolder().setTransaction(hibTx);
|
||||
|
||||
// Register the Hibernate Session's JDBC Connection for the DataSource, if set.
|
||||
if (getDataSource() != null) {
|
||||
Connection con = ((SessionImplementor) session).connection();
|
||||
ConnectionHolder conHolder = new ConnectionHolder(con);
|
||||
if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
|
||||
conHolder.setTimeoutInSeconds(timeout);
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Exposing Hibernate transaction as JDBC transaction [" + con + "]");
|
||||
}
|
||||
TransactionSynchronizationManager.bindResource(getDataSource(), conHolder);
|
||||
txObject.setConnectionHolder(conHolder);
|
||||
}
|
||||
|
||||
// Bind the session holder to the thread.
|
||||
if (txObject.isNewSessionHolder()) {
|
||||
TransactionSynchronizationManager.bindResource(getSessionFactory(), txObject.getSessionHolder());
|
||||
}
|
||||
txObject.getSessionHolder().setSynchronizedWithTransaction(true);
|
||||
}
|
||||
|
||||
catch (Throwable ex) {
|
||||
if (txObject.isNewSession()) {
|
||||
try {
|
||||
if (session.getTransaction().isActive()) {
|
||||
session.getTransaction().rollback();
|
||||
}
|
||||
}
|
||||
catch (Throwable ex2) {
|
||||
logger.debug("Could not rollback Session after failed transaction begin", ex);
|
||||
}
|
||||
finally {
|
||||
SessionFactoryUtils.closeSession(session);
|
||||
txObject.setSessionHolder(null);
|
||||
}
|
||||
}
|
||||
throw new CannotCreateTransactionException("Could not open Hibernate Session for transaction", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object doSuspend(Object transaction) {
|
||||
HibernateTransactionObject txObject = (HibernateTransactionObject) transaction;
|
||||
txObject.setSessionHolder(null);
|
||||
SessionHolder sessionHolder =
|
||||
(SessionHolder) TransactionSynchronizationManager.unbindResource(getSessionFactory());
|
||||
txObject.setConnectionHolder(null);
|
||||
ConnectionHolder connectionHolder = null;
|
||||
if (getDataSource() != null) {
|
||||
connectionHolder = (ConnectionHolder) TransactionSynchronizationManager.unbindResource(getDataSource());
|
||||
}
|
||||
return new SuspendedResourcesHolder(sessionHolder, connectionHolder);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doResume(Object transaction, Object suspendedResources) {
|
||||
SuspendedResourcesHolder resourcesHolder = (SuspendedResourcesHolder) suspendedResources;
|
||||
if (TransactionSynchronizationManager.hasResource(getSessionFactory())) {
|
||||
// From non-transactional code running in active transaction synchronization
|
||||
// -> can be safely removed, will be closed on transaction completion.
|
||||
TransactionSynchronizationManager.unbindResource(getSessionFactory());
|
||||
}
|
||||
TransactionSynchronizationManager.bindResource(getSessionFactory(), resourcesHolder.getSessionHolder());
|
||||
if (getDataSource() != null) {
|
||||
TransactionSynchronizationManager.bindResource(getDataSource(), resourcesHolder.getConnectionHolder());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doCommit(DefaultTransactionStatus status) {
|
||||
HibernateTransactionObject txObject = (HibernateTransactionObject) status.getTransaction();
|
||||
if (status.isDebug()) {
|
||||
logger.debug("Committing Hibernate transaction on Session [" +
|
||||
txObject.getSessionHolder().getSession() + "]");
|
||||
}
|
||||
try {
|
||||
txObject.getSessionHolder().getTransaction().commit();
|
||||
}
|
||||
catch (org.hibernate.TransactionException ex) {
|
||||
// assumably from commit call to the underlying JDBC connection
|
||||
throw new TransactionSystemException("Could not commit Hibernate transaction", ex);
|
||||
}
|
||||
catch (HibernateException ex) {
|
||||
// assumably failed to flush changes to database
|
||||
throw convertHibernateAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doRollback(DefaultTransactionStatus status) {
|
||||
HibernateTransactionObject txObject = (HibernateTransactionObject) status.getTransaction();
|
||||
if (status.isDebug()) {
|
||||
logger.debug("Rolling back Hibernate transaction on Session [" +
|
||||
txObject.getSessionHolder().getSession() + "]");
|
||||
}
|
||||
try {
|
||||
txObject.getSessionHolder().getTransaction().rollback();
|
||||
}
|
||||
catch (org.hibernate.TransactionException ex) {
|
||||
throw new TransactionSystemException("Could not roll back Hibernate transaction", ex);
|
||||
}
|
||||
catch (HibernateException ex) {
|
||||
// Shouldn't really happen, as a rollback doesn't cause a flush.
|
||||
throw convertHibernateAccessException(ex);
|
||||
}
|
||||
finally {
|
||||
if (!txObject.isNewSession() && !this.hibernateManagedSession) {
|
||||
// Clear all pending inserts/updates/deletes in the Session.
|
||||
// Necessary for pre-bound Sessions, to avoid inconsistent state.
|
||||
txObject.getSessionHolder().getSession().clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doSetRollbackOnly(DefaultTransactionStatus status) {
|
||||
HibernateTransactionObject txObject = (HibernateTransactionObject) status.getTransaction();
|
||||
if (status.isDebug()) {
|
||||
logger.debug("Setting Hibernate transaction on Session [" +
|
||||
txObject.getSessionHolder().getSession() + "] rollback-only");
|
||||
}
|
||||
txObject.setRollbackOnly();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doCleanupAfterCompletion(Object transaction) {
|
||||
HibernateTransactionObject txObject = (HibernateTransactionObject) transaction;
|
||||
|
||||
// Remove the session holder from the thread.
|
||||
if (txObject.isNewSessionHolder()) {
|
||||
TransactionSynchronizationManager.unbindResource(getSessionFactory());
|
||||
}
|
||||
|
||||
// Remove the JDBC connection holder from the thread, if exposed.
|
||||
if (getDataSource() != null) {
|
||||
TransactionSynchronizationManager.unbindResource(getDataSource());
|
||||
}
|
||||
|
||||
Session session = txObject.getSessionHolder().getSession();
|
||||
if (this.prepareConnection && session.isConnected() && isSameConnectionForEntireSession(session)) {
|
||||
// We're running with connection release mode "on_close": We're able to reset
|
||||
// the isolation level and/or read-only flag of the JDBC Connection here.
|
||||
// Else, we need to rely on the connection pool to perform proper cleanup.
|
||||
try {
|
||||
Connection con = ((SessionImplementor) session).connection();
|
||||
Integer previousHoldability = txObject.getPreviousHoldability();
|
||||
if (previousHoldability != null) {
|
||||
con.setHoldability(previousHoldability);
|
||||
}
|
||||
DataSourceUtils.resetConnectionAfterTransaction(con, txObject.getPreviousIsolationLevel());
|
||||
}
|
||||
catch (HibernateException ex) {
|
||||
logger.debug("Could not access JDBC Connection of Hibernate Session", ex);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
logger.debug("Could not reset JDBC Connection after transaction", ex);
|
||||
}
|
||||
}
|
||||
|
||||
if (txObject.isNewSession()) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Closing Hibernate Session [" + session + "] after transaction");
|
||||
}
|
||||
SessionFactoryUtils.closeSession(session);
|
||||
}
|
||||
else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Not closing pre-bound Hibernate Session [" + session + "] after transaction");
|
||||
}
|
||||
if (txObject.getSessionHolder().getPreviousFlushMode() != null) {
|
||||
session.setFlushMode(txObject.getSessionHolder().getPreviousFlushMode());
|
||||
}
|
||||
if (!this.allowResultAccessAfterCompletion && !this.hibernateManagedSession) {
|
||||
disconnectOnCompletion(session);
|
||||
}
|
||||
}
|
||||
txObject.getSessionHolder().clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect a pre-existing Hibernate Session on transaction completion,
|
||||
* returning its database connection but preserving its entity state.
|
||||
* <p>The default implementation simply calls {@link Session#disconnect()}.
|
||||
* Subclasses may override this with a no-op or with fine-tuned disconnection logic.
|
||||
* @param session the Hibernate Session to disconnect
|
||||
* @since 4.1.2
|
||||
* @see org.hibernate.Session#disconnect()
|
||||
*/
|
||||
protected void disconnectOnCompletion(Session session) {
|
||||
session.disconnect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the given Hibernate Session will always hold the same
|
||||
* JDBC Connection. This is used to check whether the transaction manager
|
||||
* can safely prepare and clean up the JDBC Connection used for a transaction.
|
||||
* <p>The default implementation checks the Session's connection release mode
|
||||
* to be "on_close".
|
||||
* @param session the Hibernate Session to check
|
||||
* @see org.hibernate.engine.transaction.spi.TransactionContext#getConnectionReleaseMode()
|
||||
* @see org.hibernate.ConnectionReleaseMode#ON_CLOSE
|
||||
*/
|
||||
protected boolean isSameConnectionForEntireSession(Session session) {
|
||||
if (!(session instanceof TransactionContext)) {
|
||||
// The best we can do is to assume we're safe.
|
||||
return true;
|
||||
}
|
||||
ConnectionReleaseMode releaseMode = ((TransactionContext) session).getConnectionReleaseMode();
|
||||
return ConnectionReleaseMode.ON_CLOSE.equals(releaseMode);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert the given HibernateException to an appropriate exception
|
||||
* from the {@code org.springframework.dao} hierarchy.
|
||||
* <p>Will automatically apply a specified SQLExceptionTranslator to a
|
||||
* Hibernate JDBCException, else rely on Hibernate's default translation.
|
||||
* @param ex HibernateException that occurred
|
||||
* @return a corresponding DataAccessException
|
||||
* @see SessionFactoryUtils#convertHibernateAccessException
|
||||
*/
|
||||
protected DataAccessException convertHibernateAccessException(HibernateException ex) {
|
||||
return SessionFactoryUtils.convertHibernateAccessException(ex);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Hibernate transaction object, representing a SessionHolder.
|
||||
* Used as transaction object by HibernateTransactionManager.
|
||||
*/
|
||||
private class HibernateTransactionObject extends JdbcTransactionObjectSupport {
|
||||
|
||||
private SessionHolder sessionHolder;
|
||||
|
||||
private boolean newSessionHolder;
|
||||
|
||||
private boolean newSession;
|
||||
|
||||
private Integer previousHoldability;
|
||||
|
||||
public void setSession(Session session) {
|
||||
this.sessionHolder = new SessionHolder(session);
|
||||
this.newSessionHolder = true;
|
||||
this.newSession = true;
|
||||
}
|
||||
|
||||
public void setExistingSession(Session session) {
|
||||
this.sessionHolder = new SessionHolder(session);
|
||||
this.newSessionHolder = true;
|
||||
this.newSession = false;
|
||||
}
|
||||
|
||||
public void setSessionHolder(SessionHolder sessionHolder) {
|
||||
this.sessionHolder = sessionHolder;
|
||||
this.newSessionHolder = false;
|
||||
this.newSession = false;
|
||||
}
|
||||
|
||||
public SessionHolder getSessionHolder() {
|
||||
return this.sessionHolder;
|
||||
}
|
||||
|
||||
public boolean isNewSessionHolder() {
|
||||
return this.newSessionHolder;
|
||||
}
|
||||
|
||||
public boolean isNewSession() {
|
||||
return this.newSession;
|
||||
}
|
||||
|
||||
public void setPreviousHoldability(Integer previousHoldability) {
|
||||
this.previousHoldability = previousHoldability;
|
||||
}
|
||||
|
||||
public Integer getPreviousHoldability() {
|
||||
return this.previousHoldability;
|
||||
}
|
||||
|
||||
public boolean hasSpringManagedTransaction() {
|
||||
return (this.sessionHolder != null && this.sessionHolder.getTransaction() != null);
|
||||
}
|
||||
|
||||
public boolean hasHibernateManagedTransaction() {
|
||||
return (this.sessionHolder != null && this.sessionHolder.getSession().getTransaction().isActive());
|
||||
}
|
||||
|
||||
public void setRollbackOnly() {
|
||||
this.sessionHolder.setRollbackOnly();
|
||||
if (hasConnectionHolder()) {
|
||||
getConnectionHolder().setRollbackOnly();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRollbackOnly() {
|
||||
return this.sessionHolder.isRollbackOnly() ||
|
||||
(hasConnectionHolder() && getConnectionHolder().isRollbackOnly());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() {
|
||||
try {
|
||||
this.sessionHolder.getSession().flush();
|
||||
}
|
||||
catch (HibernateException ex) {
|
||||
throw convertHibernateAccessException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Holder for suspended resources.
|
||||
* Used internally by {@code doSuspend} and {@code doResume}.
|
||||
*/
|
||||
private static class SuspendedResourcesHolder {
|
||||
|
||||
private final SessionHolder sessionHolder;
|
||||
|
||||
private final ConnectionHolder connectionHolder;
|
||||
|
||||
private SuspendedResourcesHolder(SessionHolder sessionHolder, ConnectionHolder conHolder) {
|
||||
this.sessionHolder = sessionHolder;
|
||||
this.connectionHolder = conHolder;
|
||||
}
|
||||
|
||||
private SessionHolder getSessionHolder() {
|
||||
return this.sessionHolder;
|
||||
}
|
||||
|
||||
private ConnectionHolder getConnectionHolder() {
|
||||
return this.connectionHolder;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,491 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate4;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Properties;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.hibernate.Interceptor;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.cache.spi.RegionFactory;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.context.ResourceLoaderAware;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
||||
import org.springframework.core.io.support.ResourcePatternResolver;
|
||||
import org.springframework.core.io.support.ResourcePatternUtils;
|
||||
import org.springframework.core.type.filter.TypeFilter;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.beans.factory.FactoryBean} that creates a Hibernate
|
||||
* {@link org.hibernate.SessionFactory}. This is the usual way to set up a shared
|
||||
* Hibernate SessionFactory in a Spring application context; the SessionFactory can
|
||||
* then be passed to Hibernate-based data access objects via dependency injection.
|
||||
*
|
||||
* <p><b>This variant of LocalSessionFactoryBean requires Hibernate 4.0 or higher.</b>
|
||||
* As of Spring 4.0, it is compatible with (the quite refactored) Hibernate 4.3 as well.
|
||||
* We recommend using the latest Hibernate 4.2.x or 4.3.x version, depending on whether
|
||||
* you need to remain JPA 2.0 compatible at runtime (Hibernate 4.2) or can upgrade to
|
||||
* JPA 2.1 (Hibernate 4.3).
|
||||
*
|
||||
* <p>This class is similar in role to the same-named class in the {@code orm.hibernate3}
|
||||
* package. However, in practice, it is closer to {@code AnnotationSessionFactoryBean}
|
||||
* since its core purpose is to bootstrap a {@code SessionFactory} from package scanning.
|
||||
*
|
||||
* <p><b>NOTE:</b> To set up Hibernate 4 for Spring-driven JTA transactions, make
|
||||
* sure to either specify the {@link #setJtaTransactionManager "jtaTransactionManager"}
|
||||
* bean property or to set the "hibernate.transaction.factory_class" property to
|
||||
* {@link org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory}.
|
||||
* Otherwise, Hibernate's smart flushing mechanism won't work properly.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.1
|
||||
* @see #setDataSource
|
||||
* @see #setPackagesToScan
|
||||
* @see LocalSessionFactoryBuilder
|
||||
*/
|
||||
public class LocalSessionFactoryBean extends HibernateExceptionTranslator
|
||||
implements FactoryBean<SessionFactory>, ResourceLoaderAware, InitializingBean, DisposableBean {
|
||||
|
||||
private DataSource dataSource;
|
||||
|
||||
private Resource[] configLocations;
|
||||
|
||||
private String[] mappingResources;
|
||||
|
||||
private Resource[] mappingLocations;
|
||||
|
||||
private Resource[] cacheableMappingLocations;
|
||||
|
||||
private Resource[] mappingJarLocations;
|
||||
|
||||
private Resource[] mappingDirectoryLocations;
|
||||
|
||||
private Interceptor entityInterceptor;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private org.hibernate.cfg.NamingStrategy namingStrategy;
|
||||
|
||||
private Object jtaTransactionManager;
|
||||
|
||||
private Object multiTenantConnectionProvider;
|
||||
|
||||
private Object currentTenantIdentifierResolver;
|
||||
|
||||
private RegionFactory cacheRegionFactory;
|
||||
|
||||
private TypeFilter[] entityTypeFilters;
|
||||
|
||||
private Properties hibernateProperties;
|
||||
|
||||
private Class<?>[] annotatedClasses;
|
||||
|
||||
private String[] annotatedPackages;
|
||||
|
||||
private String[] packagesToScan;
|
||||
|
||||
private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
|
||||
|
||||
private Configuration configuration;
|
||||
|
||||
private SessionFactory sessionFactory;
|
||||
|
||||
|
||||
/**
|
||||
* Set the DataSource to be used by the SessionFactory.
|
||||
* If set, this will override corresponding settings in Hibernate properties.
|
||||
* <p>If this is set, the Hibernate settings should not define
|
||||
* a connection provider to avoid meaningless double configuration.
|
||||
*/
|
||||
public void setDataSource(DataSource dataSource) {
|
||||
this.dataSource = dataSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the location of a single Hibernate XML config file, for example as
|
||||
* classpath resource "classpath:hibernate.cfg.xml".
|
||||
* <p>Note: Can be omitted when all necessary properties and mapping
|
||||
* resources are specified locally via this bean.
|
||||
* @see org.hibernate.cfg.Configuration#configure(java.net.URL)
|
||||
*/
|
||||
public void setConfigLocation(Resource configLocation) {
|
||||
this.configLocations = new Resource[] {configLocation};
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the locations of multiple Hibernate XML config files, for example as
|
||||
* classpath resources "classpath:hibernate.cfg.xml,classpath:extension.cfg.xml".
|
||||
* <p>Note: Can be omitted when all necessary properties and mapping
|
||||
* resources are specified locally via this bean.
|
||||
* @see org.hibernate.cfg.Configuration#configure(java.net.URL)
|
||||
*/
|
||||
public void setConfigLocations(Resource... configLocations) {
|
||||
this.configLocations = configLocations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Hibernate mapping resources to be found in the class path,
|
||||
* like "example.hbm.xml" or "mypackage/example.hbm.xml".
|
||||
* Analogous to mapping entries in a Hibernate XML config file.
|
||||
* Alternative to the more generic setMappingLocations method.
|
||||
* <p>Can be used to add to mappings from a Hibernate XML config file,
|
||||
* or to specify all mappings locally.
|
||||
* @see #setMappingLocations
|
||||
* @see org.hibernate.cfg.Configuration#addResource
|
||||
*/
|
||||
public void setMappingResources(String... mappingResources) {
|
||||
this.mappingResources = mappingResources;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set locations of Hibernate mapping files, for example as classpath
|
||||
* resource "classpath:example.hbm.xml". Supports any resource location
|
||||
* via Spring's resource abstraction, for example relative paths like
|
||||
* "WEB-INF/mappings/example.hbm.xml" when running in an application context.
|
||||
* <p>Can be used to add to mappings from a Hibernate XML config file,
|
||||
* or to specify all mappings locally.
|
||||
* @see org.hibernate.cfg.Configuration#addInputStream
|
||||
*/
|
||||
public void setMappingLocations(Resource... mappingLocations) {
|
||||
this.mappingLocations = mappingLocations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set locations of cacheable Hibernate mapping files, for example as web app
|
||||
* resource "/WEB-INF/mapping/example.hbm.xml". Supports any resource location
|
||||
* via Spring's resource abstraction, as long as the resource can be resolved
|
||||
* in the file system.
|
||||
* <p>Can be used to add to mappings from a Hibernate XML config file,
|
||||
* or to specify all mappings locally.
|
||||
* @see org.hibernate.cfg.Configuration#addCacheableFile(java.io.File)
|
||||
*/
|
||||
public void setCacheableMappingLocations(Resource... cacheableMappingLocations) {
|
||||
this.cacheableMappingLocations = cacheableMappingLocations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set locations of jar files that contain Hibernate mapping resources,
|
||||
* like "WEB-INF/lib/example.hbm.jar".
|
||||
* <p>Can be used to add to mappings from a Hibernate XML config file,
|
||||
* or to specify all mappings locally.
|
||||
* @see org.hibernate.cfg.Configuration#addJar(java.io.File)
|
||||
*/
|
||||
public void setMappingJarLocations(Resource... mappingJarLocations) {
|
||||
this.mappingJarLocations = mappingJarLocations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set locations of directories that contain Hibernate mapping resources,
|
||||
* like "WEB-INF/mappings".
|
||||
* <p>Can be used to add to mappings from a Hibernate XML config file,
|
||||
* or to specify all mappings locally.
|
||||
* @see org.hibernate.cfg.Configuration#addDirectory(java.io.File)
|
||||
*/
|
||||
public void setMappingDirectoryLocations(Resource... mappingDirectoryLocations) {
|
||||
this.mappingDirectoryLocations = mappingDirectoryLocations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a Hibernate entity interceptor that allows to inspect and change
|
||||
* property values before writing to and reading from the database.
|
||||
* Will get applied to any new Session created by this factory.
|
||||
* @see org.hibernate.cfg.Configuration#setInterceptor
|
||||
*/
|
||||
public void setEntityInterceptor(Interceptor entityInterceptor) {
|
||||
this.entityInterceptor = entityInterceptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a Hibernate NamingStrategy for the SessionFactory, determining the
|
||||
* physical column and table names given the info in the mapping document.
|
||||
* @see org.hibernate.cfg.Configuration#setNamingStrategy
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public void setNamingStrategy(org.hibernate.cfg.NamingStrategy namingStrategy) {
|
||||
this.namingStrategy = namingStrategy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Spring {@link org.springframework.transaction.jta.JtaTransactionManager}
|
||||
* or the JTA {@link javax.transaction.TransactionManager} to be used with Hibernate,
|
||||
* if any. Implicitly sets up {@code JtaPlatform} and {@code CMTTransactionStrategy}.
|
||||
* @see LocalSessionFactoryBuilder#setJtaTransactionManager
|
||||
*/
|
||||
public void setJtaTransactionManager(Object jtaTransactionManager) {
|
||||
this.jtaTransactionManager = jtaTransactionManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a Hibernate 4.1/4.2/4.3 {@code MultiTenantConnectionProvider} to be passed
|
||||
* on to the SessionFactory: as an instance, a Class, or a String class name.
|
||||
* <p>Note that the package location of the {@code MultiTenantConnectionProvider}
|
||||
* interface changed between Hibernate 4.2 and 4.3. This method accepts both variants.
|
||||
* @since 4.0
|
||||
* @see LocalSessionFactoryBuilder#setMultiTenantConnectionProvider
|
||||
*/
|
||||
public void setMultiTenantConnectionProvider(Object multiTenantConnectionProvider) {
|
||||
this.multiTenantConnectionProvider = multiTenantConnectionProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a Hibernate 4.1/4.2/4.3 {@code CurrentTenantIdentifierResolver} to be passed
|
||||
* on to the SessionFactory: as an instance, a Class, or a String class name.
|
||||
* @since 4.0
|
||||
* @see LocalSessionFactoryBuilder#setCurrentTenantIdentifierResolver
|
||||
*/
|
||||
public void setCurrentTenantIdentifierResolver(Object currentTenantIdentifierResolver) {
|
||||
this.currentTenantIdentifierResolver = currentTenantIdentifierResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Hibernate RegionFactory to use for the SessionFactory.
|
||||
* Allows for using a Spring-managed RegionFactory instance.
|
||||
* <p>Note: If this is set, the Hibernate settings should not define a
|
||||
* cache provider to avoid meaningless double configuration.
|
||||
* @since 4.0
|
||||
* @see org.hibernate.cache.spi.RegionFactory
|
||||
* @see LocalSessionFactoryBuilder#setCacheRegionFactory
|
||||
*/
|
||||
public void setCacheRegionFactory(RegionFactory cacheRegionFactory) {
|
||||
this.cacheRegionFactory = cacheRegionFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify custom type filters for Spring-based scanning for entity classes.
|
||||
* <p>Default is to search all specified packages for classes annotated with
|
||||
* {@code @javax.persistence.Entity}, {@code @javax.persistence.Embeddable}
|
||||
* or {@code @javax.persistence.MappedSuperclass}.
|
||||
* @since 4.1
|
||||
* @see #setPackagesToScan
|
||||
*/
|
||||
public void setEntityTypeFilters(TypeFilter... entityTypeFilters) {
|
||||
this.entityTypeFilters = entityTypeFilters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Hibernate properties, such as "hibernate.dialect".
|
||||
* <p>Note: Do not specify a transaction provider here when using
|
||||
* Spring-driven transactions. It is also advisable to omit connection
|
||||
* provider settings and use a Spring-set DataSource instead.
|
||||
* @see #setDataSource
|
||||
*/
|
||||
public void setHibernateProperties(Properties hibernateProperties) {
|
||||
this.hibernateProperties = hibernateProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Hibernate properties, if any. Mainly available for
|
||||
* configuration through property paths that specify individual keys.
|
||||
*/
|
||||
public Properties getHibernateProperties() {
|
||||
if (this.hibernateProperties == null) {
|
||||
this.hibernateProperties = new Properties();
|
||||
}
|
||||
return this.hibernateProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify annotated entity classes to register with this Hibernate SessionFactory.
|
||||
* @see org.hibernate.cfg.Configuration#addAnnotatedClass(Class)
|
||||
*/
|
||||
public void setAnnotatedClasses(Class<?>... annotatedClasses) {
|
||||
this.annotatedClasses = annotatedClasses;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the names of annotated packages, for which package-level
|
||||
* annotation metadata will be read.
|
||||
* @see org.hibernate.cfg.Configuration#addPackage(String)
|
||||
*/
|
||||
public void setAnnotatedPackages(String... annotatedPackages) {
|
||||
this.annotatedPackages = annotatedPackages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify packages to search for autodetection of your entity classes in the
|
||||
* classpath. This is analogous to Spring's component-scan feature
|
||||
* ({@link org.springframework.context.annotation.ClassPathBeanDefinitionScanner}).
|
||||
*/
|
||||
public void setPackagesToScan(String... packagesToScan) {
|
||||
this.packagesToScan = packagesToScan;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setResourceLoader(ResourceLoader resourceLoader) {
|
||||
this.resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws IOException {
|
||||
LocalSessionFactoryBuilder sfb = new LocalSessionFactoryBuilder(this.dataSource, this.resourcePatternResolver);
|
||||
|
||||
if (this.configLocations != null) {
|
||||
for (Resource resource : this.configLocations) {
|
||||
// Load Hibernate configuration from given location.
|
||||
sfb.configure(resource.getURL());
|
||||
}
|
||||
}
|
||||
|
||||
if (this.mappingResources != null) {
|
||||
// Register given Hibernate mapping definitions, contained in resource files.
|
||||
for (String mapping : this.mappingResources) {
|
||||
Resource mr = new ClassPathResource(mapping.trim(), this.resourcePatternResolver.getClassLoader());
|
||||
sfb.addInputStream(mr.getInputStream());
|
||||
}
|
||||
}
|
||||
|
||||
if (this.mappingLocations != null) {
|
||||
// Register given Hibernate mapping definitions, contained in resource files.
|
||||
for (Resource resource : this.mappingLocations) {
|
||||
sfb.addInputStream(resource.getInputStream());
|
||||
}
|
||||
}
|
||||
|
||||
if (this.cacheableMappingLocations != null) {
|
||||
// Register given cacheable Hibernate mapping definitions, read from the file system.
|
||||
for (Resource resource : this.cacheableMappingLocations) {
|
||||
sfb.addCacheableFile(resource.getFile());
|
||||
}
|
||||
}
|
||||
|
||||
if (this.mappingJarLocations != null) {
|
||||
// Register given Hibernate mapping definitions, contained in jar files.
|
||||
for (Resource resource : this.mappingJarLocations) {
|
||||
sfb.addJar(resource.getFile());
|
||||
}
|
||||
}
|
||||
|
||||
if (this.mappingDirectoryLocations != null) {
|
||||
// Register all Hibernate mapping definitions in the given directories.
|
||||
for (Resource resource : this.mappingDirectoryLocations) {
|
||||
File file = resource.getFile();
|
||||
if (!file.isDirectory()) {
|
||||
throw new IllegalArgumentException(
|
||||
"Mapping directory location [" + resource + "] does not denote a directory");
|
||||
}
|
||||
sfb.addDirectory(file);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.entityInterceptor != null) {
|
||||
sfb.setInterceptor(this.entityInterceptor);
|
||||
}
|
||||
|
||||
if (this.namingStrategy != null) {
|
||||
sfb.setNamingStrategy(this.namingStrategy);
|
||||
}
|
||||
|
||||
if (this.jtaTransactionManager != null) {
|
||||
sfb.setJtaTransactionManager(this.jtaTransactionManager);
|
||||
}
|
||||
|
||||
if (this.multiTenantConnectionProvider != null) {
|
||||
sfb.setMultiTenantConnectionProvider(this.multiTenantConnectionProvider);
|
||||
}
|
||||
|
||||
if (this.currentTenantIdentifierResolver != null) {
|
||||
sfb.setCurrentTenantIdentifierResolver(this.currentTenantIdentifierResolver);
|
||||
}
|
||||
|
||||
if (this.cacheRegionFactory != null) {
|
||||
sfb.setCacheRegionFactory(this.cacheRegionFactory);
|
||||
}
|
||||
|
||||
if (this.entityTypeFilters != null) {
|
||||
sfb.setEntityTypeFilters(this.entityTypeFilters);
|
||||
}
|
||||
|
||||
if (this.hibernateProperties != null) {
|
||||
sfb.addProperties(this.hibernateProperties);
|
||||
}
|
||||
|
||||
if (this.annotatedClasses != null) {
|
||||
sfb.addAnnotatedClasses(this.annotatedClasses);
|
||||
}
|
||||
|
||||
if (this.annotatedPackages != null) {
|
||||
sfb.addPackages(this.annotatedPackages);
|
||||
}
|
||||
|
||||
if (this.packagesToScan != null) {
|
||||
sfb.scanPackages(this.packagesToScan);
|
||||
}
|
||||
|
||||
// Build SessionFactory instance.
|
||||
this.configuration = sfb;
|
||||
this.sessionFactory = buildSessionFactory(sfb);
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses can override this method to perform custom initialization
|
||||
* of the SessionFactory instance, creating it via the given Configuration
|
||||
* object that got prepared by this LocalSessionFactoryBean.
|
||||
* <p>The default implementation invokes LocalSessionFactoryBuilder's buildSessionFactory.
|
||||
* A custom implementation could prepare the instance in a specific way (e.g. applying
|
||||
* a custom ServiceRegistry) or use a custom SessionFactoryImpl subclass.
|
||||
* @param sfb LocalSessionFactoryBuilder prepared by this LocalSessionFactoryBean
|
||||
* @return the SessionFactory instance
|
||||
* @see LocalSessionFactoryBuilder#buildSessionFactory
|
||||
*/
|
||||
protected SessionFactory buildSessionFactory(LocalSessionFactoryBuilder sfb) {
|
||||
return sfb.buildSessionFactory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Hibernate Configuration object used to build the SessionFactory.
|
||||
* Allows for access to configuration metadata stored there (rarely needed).
|
||||
* @throws IllegalStateException if the Configuration object has not been initialized yet
|
||||
*/
|
||||
public final Configuration getConfiguration() {
|
||||
if (this.configuration == null) {
|
||||
throw new IllegalStateException("Configuration not initialized yet");
|
||||
}
|
||||
return this.configuration;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public SessionFactory getObject() {
|
||||
return this.sessionFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
return (this.sessionFactory != null ? this.sessionFactory.getClass() : SessionFactory.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
this.sessionFactory.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,393 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate4;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import javax.persistence.AttributeConverter;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
import javax.sql.DataSource;
|
||||
import javax.transaction.TransactionManager;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.cache.spi.RegionFactory;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.cfg.Settings;
|
||||
import org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
||||
import org.springframework.core.io.support.ResourcePatternResolver;
|
||||
import org.springframework.core.io.support.ResourcePatternUtils;
|
||||
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
|
||||
import org.springframework.core.type.classreading.MetadataReader;
|
||||
import org.springframework.core.type.classreading.MetadataReaderFactory;
|
||||
import org.springframework.core.type.filter.AnnotationTypeFilter;
|
||||
import org.springframework.core.type.filter.TypeFilter;
|
||||
import org.springframework.transaction.jta.JtaTransactionManager;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* A Spring-provided extension of the standard Hibernate {@link Configuration} class,
|
||||
* adding {@link SpringSessionContext} as a default and providing convenient ways
|
||||
* to specify a DataSource and an application class loader.
|
||||
*
|
||||
* <p>This is designed for programmatic use, e.g. in {@code @Bean} factory methods.
|
||||
* Consider using {@link LocalSessionFactoryBean} for XML bean definition files.
|
||||
*
|
||||
* <p><b>Requires Hibernate 4.0 or higher.</b> As of Spring 4.0, it is compatible with
|
||||
* (the quite refactored) Hibernate 4.3 as well. We recommend using the latest
|
||||
* Hibernate 4.2.x or 4.3.x version, depending on whether you need to remain JPA 2.0
|
||||
* compatible at runtime (Hibernate 4.2) or can upgrade to JPA 2.1 (Hibernate 4.3).
|
||||
*
|
||||
* <p><b>NOTE:</b> To set up Hibernate 4 for Spring-driven JTA transactions, make
|
||||
* sure to either use the {@link #setJtaTransactionManager} method or to set the
|
||||
* "hibernate.transaction.factory_class" property to {@link CMTTransactionFactory}.
|
||||
* Otherwise, Hibernate's smart flushing mechanism won't work properly.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.1
|
||||
* @see LocalSessionFactoryBean
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class LocalSessionFactoryBuilder extends Configuration {
|
||||
|
||||
private static final String RESOURCE_PATTERN = "/**/*.class";
|
||||
|
||||
private static final String PACKAGE_INFO_SUFFIX = ".package-info";
|
||||
|
||||
private static final TypeFilter[] DEFAULT_ENTITY_TYPE_FILTERS = new TypeFilter[] {
|
||||
new AnnotationTypeFilter(Entity.class, false),
|
||||
new AnnotationTypeFilter(Embeddable.class, false),
|
||||
new AnnotationTypeFilter(MappedSuperclass.class, false)};
|
||||
|
||||
|
||||
private static TypeFilter converterTypeFilter;
|
||||
|
||||
static {
|
||||
try {
|
||||
@SuppressWarnings("unchecked")
|
||||
Class<? extends Annotation> converterAnnotation = (Class<? extends Annotation>)
|
||||
ClassUtils.forName("javax.persistence.Converter", LocalSessionFactoryBuilder.class.getClassLoader());
|
||||
converterTypeFilter = new AnnotationTypeFilter(converterAnnotation, false);
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
// JPA 2.1 API not available - Hibernate <4.3
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private final ResourcePatternResolver resourcePatternResolver;
|
||||
|
||||
private RegionFactory cacheRegionFactory;
|
||||
|
||||
private TypeFilter[] entityTypeFilters = DEFAULT_ENTITY_TYPE_FILTERS;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new LocalSessionFactoryBuilder for the given DataSource.
|
||||
* @param dataSource the JDBC DataSource that the resulting Hibernate SessionFactory should be using
|
||||
* (may be {@code null})
|
||||
*/
|
||||
public LocalSessionFactoryBuilder(DataSource dataSource) {
|
||||
this(dataSource, new PathMatchingResourcePatternResolver());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new LocalSessionFactoryBuilder for the given DataSource.
|
||||
* @param dataSource the JDBC DataSource that the resulting Hibernate SessionFactory should be using
|
||||
* (may be {@code null})
|
||||
* @param classLoader the ClassLoader to load application classes from
|
||||
*/
|
||||
public LocalSessionFactoryBuilder(DataSource dataSource, ClassLoader classLoader) {
|
||||
this(dataSource, new PathMatchingResourcePatternResolver(classLoader));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new LocalSessionFactoryBuilder for the given DataSource.
|
||||
* @param dataSource the JDBC DataSource that the resulting Hibernate SessionFactory should be using
|
||||
* (may be {@code null})
|
||||
* @param resourceLoader the ResourceLoader to load application classes from
|
||||
*/
|
||||
@SuppressWarnings("deprecation") // to be able to build against Hibernate 4.3
|
||||
public LocalSessionFactoryBuilder(DataSource dataSource, ResourceLoader resourceLoader) {
|
||||
getProperties().put(Environment.CURRENT_SESSION_CONTEXT_CLASS, SpringSessionContext.class.getName());
|
||||
if (dataSource != null) {
|
||||
getProperties().put(Environment.DATASOURCE, dataSource);
|
||||
}
|
||||
// APP_CLASSLOADER is deprecated as of Hibernate 4.3 but we need to remain compatible with 4.0+
|
||||
getProperties().put(AvailableSettings.APP_CLASSLOADER, resourceLoader.getClassLoader());
|
||||
this.resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the Spring {@link JtaTransactionManager} or the JTA {@link TransactionManager}
|
||||
* to be used with Hibernate, if any. Allows for using a Spring-managed transaction
|
||||
* manager for Hibernate 4's session and cache synchronization, with the
|
||||
* "hibernate.transaction.jta.platform" automatically set to it. Also sets
|
||||
* "hibernate.transaction.factory_class" to {@link CMTTransactionFactory},
|
||||
* instructing Hibernate to interact with externally managed transactions.
|
||||
* <p>A passed-in Spring {@link JtaTransactionManager} needs to contain a JTA
|
||||
* {@link TransactionManager} reference to be usable here, except for the WebSphere
|
||||
* case where we'll automatically set {@code WebSphereExtendedJtaPlatform} accordingly.
|
||||
* <p>Note: If this is set, the Hibernate settings should not contain a JTA platform
|
||||
* setting to avoid meaningless double configuration.
|
||||
*/
|
||||
public LocalSessionFactoryBuilder setJtaTransactionManager(Object jtaTransactionManager) {
|
||||
Assert.notNull(jtaTransactionManager, "Transaction manager reference must not be null");
|
||||
if (jtaTransactionManager instanceof JtaTransactionManager) {
|
||||
boolean webspherePresent = ClassUtils.isPresent("com.ibm.wsspi.uow.UOWManager", getClass().getClassLoader());
|
||||
if (webspherePresent) {
|
||||
getProperties().put(AvailableSettings.JTA_PLATFORM,
|
||||
ConfigurableJtaPlatform.getJtaPlatformBasePackage() + "internal.WebSphereExtendedJtaPlatform");
|
||||
}
|
||||
else {
|
||||
JtaTransactionManager jtaTm = (JtaTransactionManager) jtaTransactionManager;
|
||||
if (jtaTm.getTransactionManager() == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"Can only apply JtaTransactionManager which has a TransactionManager reference set");
|
||||
}
|
||||
getProperties().put(AvailableSettings.JTA_PLATFORM,
|
||||
new ConfigurableJtaPlatform(jtaTm.getTransactionManager(), jtaTm.getUserTransaction(),
|
||||
jtaTm.getTransactionSynchronizationRegistry()).getJtaPlatformProxy());
|
||||
}
|
||||
}
|
||||
else if (jtaTransactionManager instanceof TransactionManager) {
|
||||
getProperties().put(AvailableSettings.JTA_PLATFORM,
|
||||
new ConfigurableJtaPlatform((TransactionManager) jtaTransactionManager, null, null).getJtaPlatformProxy());
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException(
|
||||
"Unknown transaction manager type: " + jtaTransactionManager.getClass().getName());
|
||||
}
|
||||
getProperties().put(AvailableSettings.TRANSACTION_STRATEGY, new CMTTransactionFactory());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a Hibernate 4.1/4.2/4.3 {@code MultiTenantConnectionProvider} to be passed
|
||||
* on to the SessionFactory: as an instance, a Class, or a String class name.
|
||||
* <p>Note that the package location of the {@code MultiTenantConnectionProvider}
|
||||
* interface changed between Hibernate 4.2 and 4.3. This method accepts both variants.
|
||||
* @since 4.0
|
||||
* @see AvailableSettings#MULTI_TENANT_CONNECTION_PROVIDER
|
||||
*/
|
||||
public LocalSessionFactoryBuilder setMultiTenantConnectionProvider(Object multiTenantConnectionProvider) {
|
||||
getProperties().put(AvailableSettings.MULTI_TENANT_CONNECTION_PROVIDER, multiTenantConnectionProvider);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a Hibernate 4.1/4.2/4.3 {@code CurrentTenantIdentifierResolver} to be passed
|
||||
* on to the SessionFactory: as an instance, a Class, or a String class name.
|
||||
* @since 4.0
|
||||
* @see AvailableSettings#MULTI_TENANT_IDENTIFIER_RESOLVER
|
||||
*/
|
||||
public LocalSessionFactoryBuilder setCurrentTenantIdentifierResolver(Object currentTenantIdentifierResolver) {
|
||||
getProperties().put(AvailableSettings.MULTI_TENANT_IDENTIFIER_RESOLVER, currentTenantIdentifierResolver);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Hibernate RegionFactory to use for the SessionFactory.
|
||||
* Allows for using a Spring-managed RegionFactory instance.
|
||||
* <p>Note: If this is set, the Hibernate settings should not define a
|
||||
* cache provider to avoid meaningless double configuration.
|
||||
* @since 4.0
|
||||
* @see org.hibernate.cache.spi.RegionFactory
|
||||
*/
|
||||
public LocalSessionFactoryBuilder setCacheRegionFactory(RegionFactory cacheRegionFactory) {
|
||||
this.cacheRegionFactory = cacheRegionFactory;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify custom type filters for Spring-based scanning for entity classes.
|
||||
* <p>Default is to search all specified packages for classes annotated with
|
||||
* {@code @javax.persistence.Entity}, {@code @javax.persistence.Embeddable}
|
||||
* or {@code @javax.persistence.MappedSuperclass}.
|
||||
* @since 4.1
|
||||
* @see #scanPackages
|
||||
*/
|
||||
public LocalSessionFactoryBuilder setEntityTypeFilters(TypeFilter... entityTypeFilters) {
|
||||
this.entityTypeFilters = entityTypeFilters;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the given annotated classes in a batch.
|
||||
* @see #addAnnotatedClass
|
||||
* @see #scanPackages
|
||||
*/
|
||||
public LocalSessionFactoryBuilder addAnnotatedClasses(Class<?>... annotatedClasses) {
|
||||
for (Class<?> annotatedClass : annotatedClasses) {
|
||||
addAnnotatedClass(annotatedClass);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the given annotated packages in a batch.
|
||||
* @see #addPackage
|
||||
* @see #scanPackages
|
||||
*/
|
||||
public LocalSessionFactoryBuilder addPackages(String... annotatedPackages) {
|
||||
for (String annotatedPackage : annotatedPackages) {
|
||||
addPackage(annotatedPackage);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform Spring-based scanning for entity classes, registering them
|
||||
* as annotated classes with this {@code Configuration}.
|
||||
* @param packagesToScan one or more Java package names
|
||||
* @throws HibernateException if scanning fails for any reason
|
||||
*/
|
||||
public LocalSessionFactoryBuilder scanPackages(String... packagesToScan) throws HibernateException {
|
||||
Set<String> entityClassNames = new TreeSet<String>();
|
||||
Set<String> converterClassNames = new TreeSet<String>();
|
||||
Set<String> packageNames = new TreeSet<String>();
|
||||
try {
|
||||
for (String pkg : packagesToScan) {
|
||||
String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
|
||||
ClassUtils.convertClassNameToResourcePath(pkg) + RESOURCE_PATTERN;
|
||||
Resource[] resources = this.resourcePatternResolver.getResources(pattern);
|
||||
MetadataReaderFactory readerFactory = new CachingMetadataReaderFactory(this.resourcePatternResolver);
|
||||
for (Resource resource : resources) {
|
||||
if (resource.isReadable()) {
|
||||
MetadataReader reader = readerFactory.getMetadataReader(resource);
|
||||
String className = reader.getClassMetadata().getClassName();
|
||||
if (matchesEntityTypeFilter(reader, readerFactory)) {
|
||||
entityClassNames.add(className);
|
||||
}
|
||||
else if (converterTypeFilter != null && converterTypeFilter.match(reader, readerFactory)) {
|
||||
converterClassNames.add(className);
|
||||
}
|
||||
else if (className.endsWith(PACKAGE_INFO_SUFFIX)) {
|
||||
packageNames.add(className.substring(0, className.length() - PACKAGE_INFO_SUFFIX.length()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new MappingException("Failed to scan classpath for unlisted classes", ex);
|
||||
}
|
||||
try {
|
||||
ClassLoader cl = this.resourcePatternResolver.getClassLoader();
|
||||
for (String className : entityClassNames) {
|
||||
addAnnotatedClass(cl.loadClass(className));
|
||||
}
|
||||
for (String className : converterClassNames) {
|
||||
ConverterRegistrationDelegate.registerConverter(this, cl.loadClass(className));
|
||||
}
|
||||
for (String packageName : packageNames) {
|
||||
addPackage(packageName);
|
||||
}
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
throw new MappingException("Failed to load annotated classes from classpath", ex);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether any of the configured entity type filters matches
|
||||
* the current class descriptor contained in the metadata reader.
|
||||
*/
|
||||
private boolean matchesEntityTypeFilter(MetadataReader reader, MetadataReaderFactory readerFactory) throws IOException {
|
||||
if (this.entityTypeFilters != null) {
|
||||
for (TypeFilter filter : this.entityTypeFilters) {
|
||||
if (filter.match(reader, readerFactory)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Overridden methods from Hibernate's Configuration class
|
||||
|
||||
@Override
|
||||
public Settings buildSettings(Properties props, ServiceRegistry serviceRegistry) throws HibernateException {
|
||||
Settings settings = super.buildSettings(props, serviceRegistry);
|
||||
if (this.cacheRegionFactory != null) {
|
||||
try {
|
||||
Method setRegionFactory = Settings.class.getDeclaredMethod("setRegionFactory", RegionFactory.class);
|
||||
setRegionFactory.setAccessible(true);
|
||||
setRegionFactory.invoke(settings, this.cacheRegionFactory);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IllegalStateException("Failed to invoke Hibernate's setRegionFactory method", ex);
|
||||
}
|
||||
}
|
||||
return settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the {@code SessionFactory}.
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public SessionFactory buildSessionFactory() throws HibernateException {
|
||||
ClassLoader appClassLoader = (ClassLoader) getProperties().get(AvailableSettings.APP_CLASSLOADER);
|
||||
Thread currentThread = Thread.currentThread();
|
||||
ClassLoader threadContextClassLoader = currentThread.getContextClassLoader();
|
||||
boolean overrideClassLoader =
|
||||
(appClassLoader != null && !appClassLoader.equals(threadContextClassLoader));
|
||||
if (overrideClassLoader) {
|
||||
currentThread.setContextClassLoader(appClassLoader);
|
||||
}
|
||||
try {
|
||||
return super.buildSessionFactory();
|
||||
}
|
||||
finally {
|
||||
if (overrideClassLoader) {
|
||||
currentThread.setContextClassLoader(threadContextClassLoader);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Inner class to avoid hard dependency on JPA 2.1 / Hibernate 4.3.
|
||||
*/
|
||||
private static class ConverterRegistrationDelegate {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static void registerConverter(Configuration config, Class<?> converterClass) {
|
||||
config.addAttributeConverter((Class<? extends AttributeConverter<?, ?>>) converterClass);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,221 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate4;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.JDBCException;
|
||||
import org.hibernate.NonUniqueObjectException;
|
||||
import org.hibernate.NonUniqueResultException;
|
||||
import org.hibernate.ObjectDeletedException;
|
||||
import org.hibernate.PersistentObjectException;
|
||||
import org.hibernate.PessimisticLockException;
|
||||
import org.hibernate.PropertyValueException;
|
||||
import org.hibernate.QueryException;
|
||||
import org.hibernate.QueryTimeoutException;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.StaleObjectStateException;
|
||||
import org.hibernate.StaleStateException;
|
||||
import org.hibernate.TransientObjectException;
|
||||
import org.hibernate.UnresolvableObjectException;
|
||||
import org.hibernate.WrongClassException;
|
||||
import org.hibernate.dialect.lock.OptimisticEntityLockException;
|
||||
import org.hibernate.dialect.lock.PessimisticEntityLockException;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.exception.ConstraintViolationException;
|
||||
import org.hibernate.exception.DataException;
|
||||
import org.hibernate.exception.JDBCConnectionException;
|
||||
import org.hibernate.exception.LockAcquisitionException;
|
||||
import org.hibernate.exception.SQLGrammarException;
|
||||
import org.hibernate.service.spi.Wrapped;
|
||||
|
||||
import org.springframework.dao.CannotAcquireLockException;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.DataAccessResourceFailureException;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.dao.IncorrectResultSizeDataAccessException;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.dao.InvalidDataAccessResourceUsageException;
|
||||
import org.springframework.dao.PessimisticLockingFailureException;
|
||||
import org.springframework.jdbc.datasource.DataSourceUtils;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* Helper class featuring methods for Hibernate Session handling.
|
||||
* Also provides support for exception translation.
|
||||
*
|
||||
* <p>Used internally by {@link HibernateTransactionManager}.
|
||||
* Can also be used directly in application code.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.1
|
||||
* @see HibernateExceptionTranslator
|
||||
* @see HibernateTransactionManager
|
||||
*/
|
||||
public abstract class SessionFactoryUtils {
|
||||
|
||||
/**
|
||||
* Order value for TransactionSynchronization objects that clean up Hibernate Sessions.
|
||||
* Returns {@code DataSourceUtils.CONNECTION_SYNCHRONIZATION_ORDER - 100}
|
||||
* to execute Session cleanup before JDBC Connection cleanup, if any.
|
||||
* @see org.springframework.jdbc.datasource.DataSourceUtils#CONNECTION_SYNCHRONIZATION_ORDER
|
||||
*/
|
||||
public static final int SESSION_SYNCHRONIZATION_ORDER =
|
||||
DataSourceUtils.CONNECTION_SYNCHRONIZATION_ORDER - 100;
|
||||
|
||||
static final Log logger = LogFactory.getLog(SessionFactoryUtils.class);
|
||||
|
||||
/**
|
||||
* Bridging between the different ConnectionProvider package location in 4.0-4.2 vs 4.3.
|
||||
*/
|
||||
private static final Method getConnectionProviderMethod =
|
||||
ClassUtils.getMethodIfAvailable(SessionFactoryImplementor.class, "getConnectionProvider");
|
||||
|
||||
|
||||
/**
|
||||
* Determine the DataSource of the given SessionFactory.
|
||||
* @param sessionFactory the SessionFactory to check
|
||||
* @return the DataSource, or {@code null} if none found
|
||||
* @see org.hibernate.engine.spi.SessionFactoryImplementor#getConnectionProvider
|
||||
*/
|
||||
public static DataSource getDataSource(SessionFactory sessionFactory) {
|
||||
if (getConnectionProviderMethod != null && sessionFactory instanceof SessionFactoryImplementor) {
|
||||
Wrapped cp = (Wrapped) ReflectionUtils.invokeMethod(getConnectionProviderMethod, sessionFactory);
|
||||
if (cp != null) {
|
||||
return cp.unwrap(DataSource.class);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform actual closing of the Hibernate Session,
|
||||
* catching and logging any cleanup exceptions thrown.
|
||||
* @param session the Hibernate Session to close (may be {@code null})
|
||||
* @see org.hibernate.Session#close()
|
||||
*/
|
||||
public static void closeSession(Session session) {
|
||||
if (session != null) {
|
||||
try {
|
||||
session.close();
|
||||
}
|
||||
catch (HibernateException ex) {
|
||||
logger.debug("Could not close Hibernate Session", ex);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
logger.debug("Unexpected exception on closing Hibernate Session", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given HibernateException to an appropriate exception
|
||||
* from the {@code org.springframework.dao} hierarchy.
|
||||
* @param ex HibernateException that occurred
|
||||
* @return the corresponding DataAccessException instance
|
||||
* @see HibernateExceptionTranslator#convertHibernateAccessException
|
||||
* @see HibernateTransactionManager#convertHibernateAccessException
|
||||
*/
|
||||
public static DataAccessException convertHibernateAccessException(HibernateException ex) {
|
||||
if (ex instanceof JDBCConnectionException) {
|
||||
return new DataAccessResourceFailureException(ex.getMessage(), ex);
|
||||
}
|
||||
if (ex instanceof SQLGrammarException) {
|
||||
SQLGrammarException jdbcEx = (SQLGrammarException) ex;
|
||||
return new InvalidDataAccessResourceUsageException(ex.getMessage() + "; SQL [" + jdbcEx.getSQL() + "]", ex);
|
||||
}
|
||||
if (ex instanceof QueryTimeoutException) {
|
||||
QueryTimeoutException jdbcEx = (QueryTimeoutException) ex;
|
||||
return new org.springframework.dao.QueryTimeoutException(ex.getMessage() + "; SQL [" + jdbcEx.getSQL() + "]", ex);
|
||||
}
|
||||
if (ex instanceof LockAcquisitionException) {
|
||||
LockAcquisitionException jdbcEx = (LockAcquisitionException) ex;
|
||||
return new CannotAcquireLockException(ex.getMessage() + "; SQL [" + jdbcEx.getSQL() + "]", ex);
|
||||
}
|
||||
if (ex instanceof PessimisticLockException) {
|
||||
PessimisticLockException jdbcEx = (PessimisticLockException) ex;
|
||||
return new PessimisticLockingFailureException(ex.getMessage() + "; SQL [" + jdbcEx.getSQL() + "]", ex);
|
||||
}
|
||||
if (ex instanceof ConstraintViolationException) {
|
||||
ConstraintViolationException jdbcEx = (ConstraintViolationException) ex;
|
||||
return new DataIntegrityViolationException(ex.getMessage() + "; SQL [" + jdbcEx.getSQL() +
|
||||
"]; constraint [" + jdbcEx.getConstraintName() + "]", ex);
|
||||
}
|
||||
if (ex instanceof DataException) {
|
||||
DataException jdbcEx = (DataException) ex;
|
||||
return new DataIntegrityViolationException(ex.getMessage() + "; SQL [" + jdbcEx.getSQL() + "]", ex);
|
||||
}
|
||||
if (ex instanceof JDBCException) {
|
||||
return new HibernateJdbcException((JDBCException) ex);
|
||||
}
|
||||
// end of JDBCException (subclass) handling
|
||||
|
||||
if (ex instanceof QueryException) {
|
||||
return new HibernateQueryException((QueryException) ex);
|
||||
}
|
||||
if (ex instanceof NonUniqueResultException) {
|
||||
return new IncorrectResultSizeDataAccessException(ex.getMessage(), 1, ex);
|
||||
}
|
||||
if (ex instanceof NonUniqueObjectException) {
|
||||
return new DuplicateKeyException(ex.getMessage(), ex);
|
||||
}
|
||||
if (ex instanceof PropertyValueException) {
|
||||
return new DataIntegrityViolationException(ex.getMessage(), ex);
|
||||
}
|
||||
if (ex instanceof PersistentObjectException) {
|
||||
return new InvalidDataAccessApiUsageException(ex.getMessage(), ex);
|
||||
}
|
||||
if (ex instanceof TransientObjectException) {
|
||||
return new InvalidDataAccessApiUsageException(ex.getMessage(), ex);
|
||||
}
|
||||
if (ex instanceof ObjectDeletedException) {
|
||||
return new InvalidDataAccessApiUsageException(ex.getMessage(), ex);
|
||||
}
|
||||
if (ex instanceof UnresolvableObjectException) {
|
||||
return new HibernateObjectRetrievalFailureException((UnresolvableObjectException) ex);
|
||||
}
|
||||
if (ex instanceof WrongClassException) {
|
||||
return new HibernateObjectRetrievalFailureException((WrongClassException) ex);
|
||||
}
|
||||
if (ex instanceof StaleObjectStateException) {
|
||||
return new HibernateOptimisticLockingFailureException((StaleObjectStateException) ex);
|
||||
}
|
||||
if (ex instanceof StaleStateException) {
|
||||
return new HibernateOptimisticLockingFailureException((StaleStateException) ex);
|
||||
}
|
||||
if (ex instanceof OptimisticEntityLockException) {
|
||||
return new HibernateOptimisticLockingFailureException((OptimisticEntityLockException) ex);
|
||||
}
|
||||
if (ex instanceof PessimisticEntityLockException) {
|
||||
if (ex.getCause() instanceof LockAcquisitionException) {
|
||||
return new CannotAcquireLockException(ex.getMessage(), ex.getCause());
|
||||
}
|
||||
return new PessimisticLockingFailureException(ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
// fallback
|
||||
return new HibernateSystemException(ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate4;
|
||||
|
||||
import org.hibernate.FlushMode;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.Transaction;
|
||||
|
||||
import org.springframework.transaction.support.ResourceHolderSupport;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Session holder, wrapping a Hibernate Session and a Hibernate Transaction.
|
||||
* HibernateTransactionManager binds instances of this class to the thread,
|
||||
* for a given SessionFactory.
|
||||
*
|
||||
* <p>Note: This is an SPI class, not intended to be used by applications.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.1
|
||||
* @see HibernateTransactionManager
|
||||
* @see SessionFactoryUtils
|
||||
*/
|
||||
public class SessionHolder extends ResourceHolderSupport {
|
||||
|
||||
private Session session;
|
||||
|
||||
private Transaction transaction;
|
||||
|
||||
private FlushMode previousFlushMode;
|
||||
|
||||
|
||||
public SessionHolder(Session session) {
|
||||
Assert.notNull(session, "Session must not be null");
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
public Session getSession() {
|
||||
return this.session;
|
||||
}
|
||||
|
||||
public void setTransaction(Transaction transaction) {
|
||||
this.transaction = transaction;
|
||||
}
|
||||
|
||||
public Transaction getTransaction() {
|
||||
return this.transaction;
|
||||
}
|
||||
|
||||
public void setPreviousFlushMode(FlushMode previousFlushMode) {
|
||||
this.previousFlushMode = previousFlushMode;
|
||||
}
|
||||
|
||||
public FlushMode getPreviousFlushMode() {
|
||||
return this.previousFlushMode;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
super.clear();
|
||||
this.transaction = null;
|
||||
this.previousFlushMode = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate4;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.Session;
|
||||
|
||||
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
|
||||
|
||||
/**
|
||||
* Simple synchronization adapter that propagates a {@code flush()} call
|
||||
* to the underlying Hibernate Session. Used in combination with JTA.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.1
|
||||
*/
|
||||
public class SpringFlushSynchronization extends TransactionSynchronizationAdapter {
|
||||
|
||||
private final Session session;
|
||||
|
||||
|
||||
public SpringFlushSynchronization(Session session) {
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void flush() {
|
||||
try {
|
||||
SessionFactoryUtils.logger.debug("Flushing Hibernate Session on explicit request");
|
||||
this.session.flush();
|
||||
}
|
||||
catch (HibernateException ex) {
|
||||
throw SessionFactoryUtils.convertHibernateAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return (obj instanceof SpringFlushSynchronization &&
|
||||
this.session == ((SpringFlushSynchronization) obj).session);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return this.session.hashCode();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate4;
|
||||
|
||||
import org.hibernate.FlushMode;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.context.internal.JTASessionContext;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
|
||||
/**
|
||||
* Spring-specific subclass of Hibernate's JTASessionContext,
|
||||
* setting {@code FlushMode.MANUAL} for read-only transactions.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.1
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class SpringJtaSessionContext extends JTASessionContext {
|
||||
|
||||
public SpringJtaSessionContext(SessionFactoryImplementor factory) {
|
||||
super(factory);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Session buildOrObtainSession() {
|
||||
Session session = super.buildOrObtainSession();
|
||||
if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
|
||||
session.setFlushMode(FlushMode.MANUAL);
|
||||
}
|
||||
return session;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,138 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate4;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import javax.transaction.Status;
|
||||
import javax.transaction.SystemException;
|
||||
import javax.transaction.TransactionManager;
|
||||
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.hibernate.FlushMode;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.context.spi.CurrentSessionContext;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* Implementation of Hibernate 3.1's CurrentSessionContext interface
|
||||
* that delegates to Spring's SessionFactoryUtils for providing a
|
||||
* Spring-managed current Session.
|
||||
*
|
||||
* <p>This CurrentSessionContext implementation can also be specified in custom
|
||||
* SessionFactory setup through the "hibernate.current_session_context_class"
|
||||
* property, with the fully qualified name of this class as value.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.1
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class SpringSessionContext implements CurrentSessionContext {
|
||||
|
||||
private final SessionFactoryImplementor sessionFactory;
|
||||
|
||||
private TransactionManager transactionManager;
|
||||
|
||||
private CurrentSessionContext jtaSessionContext;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new SpringSessionContext for the given Hibernate SessionFactory.
|
||||
* @param sessionFactory the SessionFactory to provide current Sessions for
|
||||
*/
|
||||
public SpringSessionContext(SessionFactoryImplementor sessionFactory) {
|
||||
this.sessionFactory = sessionFactory;
|
||||
try {
|
||||
Object jtaPlatform = sessionFactory.getServiceRegistry().getService(ConfigurableJtaPlatform.jtaPlatformClass);
|
||||
Method rtmMethod = ConfigurableJtaPlatform.jtaPlatformClass.getMethod("retrieveTransactionManager");
|
||||
this.transactionManager = (TransactionManager) ReflectionUtils.invokeMethod(rtmMethod, jtaPlatform);
|
||||
if (this.transactionManager != null) {
|
||||
this.jtaSessionContext = new SpringJtaSessionContext(sessionFactory);
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
LogFactory.getLog(SpringSessionContext.class).warn(
|
||||
"Could not introspect Hibernate JtaPlatform for SpringJtaSessionContext", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve the Spring-managed Session for the current thread, if any.
|
||||
*/
|
||||
@Override
|
||||
public Session currentSession() throws HibernateException {
|
||||
Object value = TransactionSynchronizationManager.getResource(this.sessionFactory);
|
||||
if (value instanceof Session) {
|
||||
return (Session) value;
|
||||
}
|
||||
else if (value instanceof SessionHolder) {
|
||||
SessionHolder sessionHolder = (SessionHolder) value;
|
||||
Session session = sessionHolder.getSession();
|
||||
if (!sessionHolder.isSynchronizedWithTransaction() &&
|
||||
TransactionSynchronizationManager.isSynchronizationActive()) {
|
||||
TransactionSynchronizationManager.registerSynchronization(
|
||||
new SpringSessionSynchronization(sessionHolder, this.sessionFactory, false));
|
||||
sessionHolder.setSynchronizedWithTransaction(true);
|
||||
// Switch to FlushMode.AUTO, as we have to assume a thread-bound Session
|
||||
// with FlushMode.MANUAL, which needs to allow flushing within the transaction.
|
||||
FlushMode flushMode = session.getFlushMode();
|
||||
if (flushMode.equals(FlushMode.MANUAL) &&
|
||||
!TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
|
||||
session.setFlushMode(FlushMode.AUTO);
|
||||
sessionHolder.setPreviousFlushMode(flushMode);
|
||||
}
|
||||
}
|
||||
return session;
|
||||
}
|
||||
|
||||
if (this.transactionManager != null) {
|
||||
try {
|
||||
if (this.transactionManager.getStatus() == Status.STATUS_ACTIVE) {
|
||||
Session session = this.jtaSessionContext.currentSession();
|
||||
if (TransactionSynchronizationManager.isSynchronizationActive()) {
|
||||
TransactionSynchronizationManager.registerSynchronization(new SpringFlushSynchronization(session));
|
||||
}
|
||||
return session;
|
||||
}
|
||||
}
|
||||
catch (SystemException ex) {
|
||||
throw new HibernateException("JTA TransactionManager found but status check failed", ex);
|
||||
}
|
||||
}
|
||||
|
||||
if (TransactionSynchronizationManager.isSynchronizationActive()) {
|
||||
Session session = this.sessionFactory.openSession();
|
||||
if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
|
||||
session.setFlushMode(FlushMode.MANUAL);
|
||||
}
|
||||
SessionHolder sessionHolder = new SessionHolder(session);
|
||||
TransactionSynchronizationManager.registerSynchronization(
|
||||
new SpringSessionSynchronization(sessionHolder, this.sessionFactory, true));
|
||||
TransactionSynchronizationManager.bindResource(this.sessionFactory, sessionHolder);
|
||||
sessionHolder.setSynchronizedWithTransaction(true);
|
||||
return session;
|
||||
}
|
||||
else {
|
||||
throw new HibernateException("Could not obtain transaction-synchronized Session for current thread");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,155 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate4;
|
||||
|
||||
import org.hibernate.FlushMode;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.transaction.support.TransactionSynchronization;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
|
||||
/**
|
||||
* Callback for resource cleanup at the end of a Spring-managed transaction
|
||||
* for a pre-bound Hibernate Session.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.1
|
||||
*/
|
||||
public class SpringSessionSynchronization implements TransactionSynchronization, Ordered {
|
||||
|
||||
private final SessionHolder sessionHolder;
|
||||
|
||||
private final SessionFactory sessionFactory;
|
||||
|
||||
private final boolean newSession;
|
||||
|
||||
private boolean holderActive = true;
|
||||
|
||||
|
||||
public SpringSessionSynchronization(SessionHolder sessionHolder, SessionFactory sessionFactory) {
|
||||
this(sessionHolder, sessionFactory, false);
|
||||
}
|
||||
|
||||
public SpringSessionSynchronization(SessionHolder sessionHolder, SessionFactory sessionFactory, boolean newSession) {
|
||||
this.sessionHolder = sessionHolder;
|
||||
this.sessionFactory = sessionFactory;
|
||||
this.newSession = newSession;
|
||||
}
|
||||
|
||||
|
||||
private Session getCurrentSession() {
|
||||
return this.sessionHolder.getSession();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return SessionFactoryUtils.SESSION_SYNCHRONIZATION_ORDER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suspend() {
|
||||
if (this.holderActive) {
|
||||
TransactionSynchronizationManager.unbindResource(this.sessionFactory);
|
||||
// Eagerly disconnect the Session here, to make release mode "on_close" work on JBoss.
|
||||
getCurrentSession().disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resume() {
|
||||
if (this.holderActive) {
|
||||
TransactionSynchronizationManager.bindResource(this.sessionFactory, this.sessionHolder);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() {
|
||||
try {
|
||||
SessionFactoryUtils.logger.debug("Flushing Hibernate Session on explicit request");
|
||||
getCurrentSession().flush();
|
||||
}
|
||||
catch (HibernateException ex) {
|
||||
throw SessionFactoryUtils.convertHibernateAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeCommit(boolean readOnly) throws DataAccessException {
|
||||
if (!readOnly) {
|
||||
Session session = getCurrentSession();
|
||||
// Read-write transaction -> flush the Hibernate Session.
|
||||
// Further check: only flush when not FlushMode.MANUAL.
|
||||
if (!session.getFlushMode().equals(FlushMode.MANUAL)) {
|
||||
try {
|
||||
SessionFactoryUtils.logger.debug("Flushing Hibernate Session on transaction synchronization");
|
||||
session.flush();
|
||||
}
|
||||
catch (HibernateException ex) {
|
||||
throw SessionFactoryUtils.convertHibernateAccessException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeCompletion() {
|
||||
try {
|
||||
Session session = this.sessionHolder.getSession();
|
||||
if (this.sessionHolder.getPreviousFlushMode() != null) {
|
||||
// In case of pre-bound Session, restore previous flush mode.
|
||||
session.setFlushMode(this.sessionHolder.getPreviousFlushMode());
|
||||
}
|
||||
// Eagerly disconnect the Session here, to make release mode "on_close" work nicely.
|
||||
session.disconnect();
|
||||
}
|
||||
finally {
|
||||
// Unbind at this point if it's a new Session...
|
||||
if (this.newSession) {
|
||||
TransactionSynchronizationManager.unbindResource(this.sessionFactory);
|
||||
this.holderActive = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterCommit() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterCompletion(int status) {
|
||||
try {
|
||||
if (status != STATUS_COMMITTED) {
|
||||
// Clear all pending inserts/updates/deletes in the Session.
|
||||
// Necessary for pre-bound Sessions, to avoid inconsistent state.
|
||||
this.sessionHolder.getSession().clear();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
this.sessionHolder.setSynchronizedWithTransaction(false);
|
||||
// Call close() at this point if it's a new Session...
|
||||
if (this.newSession) {
|
||||
SessionFactoryUtils.closeSession(this.sessionHolder.getSession());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
/**
|
||||
* Package providing integration of
|
||||
* <a href="http://www.hibernate.org">Hibernate 4.x</a>
|
||||
* with Spring concepts.
|
||||
*
|
||||
* <p>Contains an implementation of Spring's transaction SPI for local Hibernate transactions.
|
||||
* This package is intentionally rather minimal, with no template classes or the like,
|
||||
* in order to follow Hibernate recommendations as closely as possible. We recommend
|
||||
* using Hibernate's native <code>sessionFactory.getCurrentSession()</code> style.
|
||||
*
|
||||
* <p><b>This package supports Hibernate 4.x only.</b>
|
||||
* See the {@code org.springframework.orm.hibernate3} package for Hibernate 3.x support.
|
||||
* <b>Note:</b> Do not use HibernateTemplate or other classes from the hibernate3 package
|
||||
* with Hibernate 4; this will lead to class definition exceptions at runtime.
|
||||
*/
|
||||
package org.springframework.orm.hibernate4;
|
||||
|
|
@ -1,120 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate4.support;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.hibernate.SessionFactory;
|
||||
|
||||
import org.springframework.orm.hibernate4.SessionFactoryUtils;
|
||||
import org.springframework.orm.hibernate4.SessionHolder;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
import org.springframework.web.context.request.async.CallableProcessingInterceptorAdapter;
|
||||
import org.springframework.web.context.request.async.DeferredResult;
|
||||
import org.springframework.web.context.request.async.DeferredResultProcessingInterceptor;
|
||||
|
||||
/**
|
||||
* An interceptor with asynchronous web requests used in OpenSessionInViewFilter and
|
||||
* OpenSessionInViewInterceptor.
|
||||
*
|
||||
* Ensures the following:
|
||||
* 1) The session is bound/unbound when "callable processing" is started
|
||||
* 2) The session is closed if an async request times out
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 3.2.5
|
||||
*/
|
||||
class AsyncRequestInterceptor extends CallableProcessingInterceptorAdapter implements DeferredResultProcessingInterceptor {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(AsyncRequestInterceptor.class);
|
||||
|
||||
private final SessionFactory sessionFactory;
|
||||
|
||||
private final SessionHolder sessionHolder;
|
||||
|
||||
private volatile boolean timeoutInProgress;
|
||||
|
||||
|
||||
public AsyncRequestInterceptor(SessionFactory sessionFactory, SessionHolder sessionHolder) {
|
||||
this.sessionFactory = sessionFactory;
|
||||
this.sessionHolder = sessionHolder;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public <T> void preProcess(NativeWebRequest request, Callable<T> task) {
|
||||
bindSession();
|
||||
}
|
||||
|
||||
public void bindSession() {
|
||||
this.timeoutInProgress = false;
|
||||
TransactionSynchronizationManager.bindResource(this.sessionFactory, this.sessionHolder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void postProcess(NativeWebRequest request, Callable<T> task, Object concurrentResult) {
|
||||
TransactionSynchronizationManager.unbindResource(this.sessionFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Object handleTimeout(NativeWebRequest request, Callable<T> task) {
|
||||
this.timeoutInProgress = true;
|
||||
return RESULT_NONE; // give other interceptors a chance to handle the timeout
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void afterCompletion(NativeWebRequest request, Callable<T> task) throws Exception {
|
||||
closeAfterTimeout();
|
||||
}
|
||||
|
||||
private void closeAfterTimeout() {
|
||||
if (this.timeoutInProgress) {
|
||||
logger.debug("Closing Hibernate Session after async request timeout");
|
||||
SessionFactoryUtils.closeSession(this.sessionHolder.getSession());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Implementation of DeferredResultProcessingInterceptor methods
|
||||
|
||||
@Override
|
||||
public <T> void beforeConcurrentHandling(NativeWebRequest request, DeferredResult<T> deferredResult) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void preProcess(NativeWebRequest request, DeferredResult<T> deferredResult) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void postProcess(NativeWebRequest request, DeferredResult<T> deferredResult, Object result) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> boolean handleTimeout(NativeWebRequest request, DeferredResult<T> deferredResult) {
|
||||
this.timeoutInProgress = true;
|
||||
return true; // give other interceptors a chance to handle the timeout
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void afterCompletion(NativeWebRequest request, DeferredResult<T> deferredResult) {
|
||||
closeAfterTimeout();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,132 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate4.support;
|
||||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
|
||||
import org.springframework.dao.DataAccessResourceFailureException;
|
||||
import org.springframework.dao.support.DaoSupport;
|
||||
import org.springframework.orm.hibernate4.HibernateTemplate;
|
||||
|
||||
/**
|
||||
* Convenient super class for Hibernate-based data access objects.
|
||||
*
|
||||
* <p>Requires a {@link org.hibernate.SessionFactory} to be set, providing a
|
||||
* {@link org.springframework.orm.hibernate4.HibernateTemplate} based on it to
|
||||
* subclasses through the {@link #getHibernateTemplate()} method.
|
||||
* Can alternatively be initialized directly with a HibernateTemplate,
|
||||
* in order to reuse the latter's settings such as the SessionFactory,
|
||||
* exception translator, flush mode, etc.
|
||||
*
|
||||
* <p>This class will create its own HibernateTemplate instance if a SessionFactory
|
||||
* is passed in. The "allowCreate" flag on that HibernateTemplate will be "true"
|
||||
* by default. A custom HibernateTemplate instance can be used through overriding
|
||||
* {@link #createHibernateTemplate}.
|
||||
*
|
||||
* <p><b>NOTE: Hibernate access code can also be coded in plain Hibernate style.
|
||||
* Hence, for newly started projects, consider adopting the standard Hibernate
|
||||
* style of coding data access objects instead, based on
|
||||
* {@link org.hibernate.SessionFactory#getCurrentSession()}.
|
||||
* This HibernateTemplate primarily exists as a migration helper for Hibernate 3
|
||||
* based data access code, to benefit from bug fixes in Hibernate 4.x.</b>
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.0.1
|
||||
* @see #setSessionFactory
|
||||
* @see #getHibernateTemplate
|
||||
* @see org.springframework.orm.hibernate4.HibernateTemplate
|
||||
*/
|
||||
public abstract class HibernateDaoSupport extends DaoSupport {
|
||||
|
||||
private HibernateTemplate hibernateTemplate;
|
||||
|
||||
|
||||
/**
|
||||
* Set the Hibernate SessionFactory to be used by this DAO.
|
||||
* Will automatically create a HibernateTemplate for the given SessionFactory.
|
||||
* @see #createHibernateTemplate
|
||||
* @see #setHibernateTemplate
|
||||
*/
|
||||
public final void setSessionFactory(SessionFactory sessionFactory) {
|
||||
if (this.hibernateTemplate == null || sessionFactory != this.hibernateTemplate.getSessionFactory()) {
|
||||
this.hibernateTemplate = createHibernateTemplate(sessionFactory);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a HibernateTemplate for the given SessionFactory.
|
||||
* Only invoked if populating the DAO with a SessionFactory reference!
|
||||
* <p>Can be overridden in subclasses to provide a HibernateTemplate instance
|
||||
* with different configuration, or a custom HibernateTemplate subclass.
|
||||
* @param sessionFactory the Hibernate SessionFactory to create a HibernateTemplate for
|
||||
* @return the new HibernateTemplate instance
|
||||
* @see #setSessionFactory
|
||||
*/
|
||||
protected HibernateTemplate createHibernateTemplate(SessionFactory sessionFactory) {
|
||||
return new HibernateTemplate(sessionFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Hibernate SessionFactory used by this DAO.
|
||||
*/
|
||||
public final SessionFactory getSessionFactory() {
|
||||
return (this.hibernateTemplate != null ? this.hibernateTemplate.getSessionFactory() : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the HibernateTemplate for this DAO explicitly,
|
||||
* as an alternative to specifying a SessionFactory.
|
||||
* @see #setSessionFactory
|
||||
*/
|
||||
public final void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
|
||||
this.hibernateTemplate = hibernateTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the HibernateTemplate for this DAO,
|
||||
* pre-initialized with the SessionFactory or set explicitly.
|
||||
* <p><b>Note: The returned HibernateTemplate is a shared instance.</b>
|
||||
* You may introspect its configuration, but not modify the configuration
|
||||
* (other than from within an {@link #initDao} implementation).
|
||||
* Consider creating a custom HibernateTemplate instance via
|
||||
* {@code new HibernateTemplate(getSessionFactory())}, in which case
|
||||
* you're allowed to customize the settings on the resulting instance.
|
||||
*/
|
||||
public final HibernateTemplate getHibernateTemplate() {
|
||||
return this.hibernateTemplate;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void checkDaoConfig() {
|
||||
if (this.hibernateTemplate == null) {
|
||||
throw new IllegalArgumentException("'sessionFactory' or 'hibernateTemplate' is required");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Conveniently obtain the current Hibernate Session.
|
||||
* @return the Hibernate Session
|
||||
* @throws DataAccessResourceFailureException if the Session couldn't be created
|
||||
* @see org.hibernate.SessionFactory#getCurrentSession()
|
||||
*/
|
||||
protected final Session currentSession() throws DataAccessResourceFailureException {
|
||||
return getSessionFactory().getCurrentSession();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,221 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate4.support;
|
||||
|
||||
import java.io.IOException;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.hibernate.FlushMode;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
|
||||
import org.springframework.dao.DataAccessResourceFailureException;
|
||||
import org.springframework.orm.hibernate4.SessionFactoryUtils;
|
||||
import org.springframework.orm.hibernate4.SessionHolder;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.context.request.async.WebAsyncManager;
|
||||
import org.springframework.web.context.request.async.WebAsyncUtils;
|
||||
import org.springframework.web.context.support.WebApplicationContextUtils;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
/**
|
||||
* Servlet Filter that binds a Hibernate Session to the thread for the entire
|
||||
* processing of the request. Intended for the "Open Session in View" pattern,
|
||||
* i.e. to allow for lazy loading in web views despite the original transactions
|
||||
* already being completed.
|
||||
*
|
||||
* <p>This filter makes Hibernate Sessions available via the current thread, which
|
||||
* will be autodetected by transaction managers. It is suitable for service layer
|
||||
* transactions via {@link org.springframework.orm.hibernate4.HibernateTransactionManager}
|
||||
* as well as for non-transactional execution (if configured appropriately).
|
||||
*
|
||||
* <p><b>NOTE</b>: This filter will by default <i>not</i> flush the Hibernate Session,
|
||||
* with the flush mode set to {@code FlushMode.NEVER}. It assumes to be used
|
||||
* in combination with service layer transactions that care for the flushing: The
|
||||
* active transaction manager will temporarily change the flush mode to
|
||||
* {@code FlushMode.AUTO} during a read-write transaction, with the flush
|
||||
* mode reset to {@code FlushMode.NEVER} at the end of each transaction.
|
||||
*
|
||||
* <p><b>WARNING:</b> Applying this filter to existing logic can cause issues that
|
||||
* have not appeared before, through the use of a single Hibernate Session for the
|
||||
* processing of an entire request. In particular, the reassociation of persistent
|
||||
* objects with a Hibernate Session has to occur at the very beginning of request
|
||||
* processing, to avoid clashes with already loaded instances of the same objects.
|
||||
*
|
||||
* <p>Looks up the SessionFactory in Spring's root web application context.
|
||||
* Supports a "sessionFactoryBeanName" filter init-param in {@code web.xml};
|
||||
* the default bean name is "sessionFactory".
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.1
|
||||
* @see #lookupSessionFactory
|
||||
* @see OpenSessionInViewInterceptor
|
||||
* @see OpenSessionInterceptor
|
||||
* @see org.springframework.orm.hibernate4.HibernateTransactionManager
|
||||
* @see org.springframework.transaction.support.TransactionSynchronizationManager
|
||||
* @see org.hibernate.SessionFactory#getCurrentSession()
|
||||
*/
|
||||
public class OpenSessionInViewFilter extends OncePerRequestFilter {
|
||||
|
||||
public static final String DEFAULT_SESSION_FACTORY_BEAN_NAME = "sessionFactory";
|
||||
|
||||
private String sessionFactoryBeanName = DEFAULT_SESSION_FACTORY_BEAN_NAME;
|
||||
|
||||
|
||||
/**
|
||||
* Set the bean name of the SessionFactory to fetch from Spring's
|
||||
* root application context. Default is "sessionFactory".
|
||||
* @see #DEFAULT_SESSION_FACTORY_BEAN_NAME
|
||||
*/
|
||||
public void setSessionFactoryBeanName(String sessionFactoryBeanName) {
|
||||
this.sessionFactoryBeanName = sessionFactoryBeanName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the bean name of the SessionFactory to fetch from Spring's
|
||||
* root application context.
|
||||
*/
|
||||
protected String getSessionFactoryBeanName() {
|
||||
return this.sessionFactoryBeanName;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns "false" so that the filter may re-bind the opened Hibernate
|
||||
* {@code Session} to each asynchronously dispatched thread and postpone
|
||||
* closing it until the very last asynchronous dispatch.
|
||||
*/
|
||||
@Override
|
||||
protected boolean shouldNotFilterAsyncDispatch() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns "false" so that the filter may provide a Hibernate
|
||||
* {@code Session} to each error dispatches.
|
||||
*/
|
||||
@Override
|
||||
protected boolean shouldNotFilterErrorDispatch() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(
|
||||
HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
|
||||
throws ServletException, IOException {
|
||||
|
||||
SessionFactory sessionFactory = lookupSessionFactory(request);
|
||||
boolean participate = false;
|
||||
|
||||
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
|
||||
String key = getAlreadyFilteredAttributeName();
|
||||
|
||||
if (TransactionSynchronizationManager.hasResource(sessionFactory)) {
|
||||
// Do not modify the Session: just set the participate flag.
|
||||
participate = true;
|
||||
}
|
||||
else {
|
||||
boolean isFirstRequest = !isAsyncDispatch(request);
|
||||
if (isFirstRequest || !applySessionBindingInterceptor(asyncManager, key)) {
|
||||
logger.debug("Opening Hibernate Session in OpenSessionInViewFilter");
|
||||
Session session = openSession(sessionFactory);
|
||||
SessionHolder sessionHolder = new SessionHolder(session);
|
||||
TransactionSynchronizationManager.bindResource(sessionFactory, sessionHolder);
|
||||
|
||||
AsyncRequestInterceptor interceptor = new AsyncRequestInterceptor(sessionFactory, sessionHolder);
|
||||
asyncManager.registerCallableInterceptor(key, interceptor);
|
||||
asyncManager.registerDeferredResultInterceptor(key, interceptor);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
|
||||
finally {
|
||||
if (!participate) {
|
||||
SessionHolder sessionHolder =
|
||||
(SessionHolder) TransactionSynchronizationManager.unbindResource(sessionFactory);
|
||||
if (!isAsyncStarted(request)) {
|
||||
logger.debug("Closing Hibernate Session in OpenSessionInViewFilter");
|
||||
SessionFactoryUtils.closeSession(sessionHolder.getSession());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up the SessionFactory that this filter should use,
|
||||
* taking the current HTTP request as argument.
|
||||
* <p>The default implementation delegates to the {@link #lookupSessionFactory()}
|
||||
* variant without arguments.
|
||||
* @param request the current request
|
||||
* @return the SessionFactory to use
|
||||
*/
|
||||
protected SessionFactory lookupSessionFactory(HttpServletRequest request) {
|
||||
return lookupSessionFactory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up the SessionFactory that this filter should use.
|
||||
* <p>The default implementation looks for a bean with the specified name
|
||||
* in Spring's root application context.
|
||||
* @return the SessionFactory to use
|
||||
* @see #getSessionFactoryBeanName
|
||||
*/
|
||||
protected SessionFactory lookupSessionFactory() {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Using SessionFactory '" + getSessionFactoryBeanName() + "' for OpenSessionInViewFilter");
|
||||
}
|
||||
WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
|
||||
return wac.getBean(getSessionFactoryBeanName(), SessionFactory.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a Session for the SessionFactory that this filter uses.
|
||||
* <p>The default implementation delegates to the {@link SessionFactory#openSession}
|
||||
* method and sets the {@link Session}'s flush mode to "MANUAL".
|
||||
* @param sessionFactory the SessionFactory that this filter uses
|
||||
* @return the Session to use
|
||||
* @throws DataAccessResourceFailureException if the Session could not be created
|
||||
* @see org.hibernate.FlushMode#MANUAL
|
||||
*/
|
||||
protected Session openSession(SessionFactory sessionFactory) throws DataAccessResourceFailureException {
|
||||
try {
|
||||
Session session = sessionFactory.openSession();
|
||||
session.setFlushMode(FlushMode.MANUAL);
|
||||
return session;
|
||||
}
|
||||
catch (HibernateException ex) {
|
||||
throw new DataAccessResourceFailureException("Could not open Hibernate Session", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean applySessionBindingInterceptor(WebAsyncManager asyncManager, String key) {
|
||||
if (asyncManager.getCallableInterceptor(key) == null) {
|
||||
return false;
|
||||
}
|
||||
((AsyncRequestInterceptor) asyncManager.getCallableInterceptor(key)).bindSession();
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,211 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate4.support;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.hibernate.FlushMode;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.DataAccessResourceFailureException;
|
||||
import org.springframework.orm.hibernate4.SessionFactoryUtils;
|
||||
import org.springframework.orm.hibernate4.SessionHolder;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.context.request.AsyncWebRequestInterceptor;
|
||||
import org.springframework.web.context.request.WebRequest;
|
||||
import org.springframework.web.context.request.async.WebAsyncManager;
|
||||
import org.springframework.web.context.request.async.WebAsyncUtils;
|
||||
|
||||
/**
|
||||
* Spring web request interceptor that binds a Hibernate {@code Session} to the
|
||||
* thread for the entire processing of the request.
|
||||
*
|
||||
* <p>This class is a concrete expression of the "Open Session in View" pattern, which
|
||||
* is a pattern that allows for the lazy loading of associations in web views despite
|
||||
* the original transactions already being completed.
|
||||
*
|
||||
* <p>This interceptor makes Hibernate Sessions available via the current thread,
|
||||
* which will be autodetected by transaction managers. It is suitable for service layer
|
||||
* transactions via {@link org.springframework.orm.hibernate4.HibernateTransactionManager}
|
||||
* as well as for non-transactional execution (if configured appropriately).
|
||||
*
|
||||
* <p>In contrast to {@link OpenSessionInViewFilter}, this interceptor is configured
|
||||
* in a Spring application context and can thus take advantage of bean wiring.
|
||||
*
|
||||
* <p><b>WARNING:</b> Applying this interceptor to existing logic can cause issues
|
||||
* that have not appeared before, through the use of a single Hibernate
|
||||
* {@code Session} for the processing of an entire request. In particular, the
|
||||
* reassociation of persistent objects with a Hibernate {@code Session} has to
|
||||
* occur at the very beginning of request processing, to avoid clashes with already
|
||||
* loaded instances of the same objects.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.1
|
||||
* @see OpenSessionInViewFilter
|
||||
* @see OpenSessionInterceptor
|
||||
* @see org.springframework.orm.hibernate4.HibernateTransactionManager
|
||||
* @see org.springframework.transaction.support.TransactionSynchronizationManager
|
||||
* @see org.hibernate.SessionFactory#getCurrentSession()
|
||||
*/
|
||||
public class OpenSessionInViewInterceptor implements AsyncWebRequestInterceptor {
|
||||
|
||||
/**
|
||||
* Suffix that gets appended to the {@code SessionFactory}
|
||||
* {@code toString()} representation for the "participate in existing
|
||||
* session handling" request attribute.
|
||||
* @see #getParticipateAttributeName
|
||||
*/
|
||||
public static final String PARTICIPATE_SUFFIX = ".PARTICIPATE";
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private SessionFactory sessionFactory;
|
||||
|
||||
|
||||
/**
|
||||
* Set the Hibernate SessionFactory that should be used to create Hibernate Sessions.
|
||||
*/
|
||||
public void setSessionFactory(SessionFactory sessionFactory) {
|
||||
this.sessionFactory = sessionFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Hibernate SessionFactory that should be used to create Hibernate Sessions.
|
||||
*/
|
||||
public SessionFactory getSessionFactory() {
|
||||
return this.sessionFactory;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Open a new Hibernate {@code Session} according and bind it to the thread via the
|
||||
* {@link org.springframework.transaction.support.TransactionSynchronizationManager}.
|
||||
*/
|
||||
@Override
|
||||
public void preHandle(WebRequest request) throws DataAccessException {
|
||||
String participateAttributeName = getParticipateAttributeName();
|
||||
|
||||
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
|
||||
if (asyncManager.hasConcurrentResult()) {
|
||||
if (applySessionBindingInterceptor(asyncManager, participateAttributeName)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (TransactionSynchronizationManager.hasResource(getSessionFactory())) {
|
||||
// Do not modify the Session: just mark the request accordingly.
|
||||
Integer count = (Integer) request.getAttribute(participateAttributeName, WebRequest.SCOPE_REQUEST);
|
||||
int newCount = (count != null ? count + 1 : 1);
|
||||
request.setAttribute(getParticipateAttributeName(), newCount, WebRequest.SCOPE_REQUEST);
|
||||
}
|
||||
else {
|
||||
logger.debug("Opening Hibernate Session in OpenSessionInViewInterceptor");
|
||||
Session session = openSession();
|
||||
SessionHolder sessionHolder = new SessionHolder(session);
|
||||
TransactionSynchronizationManager.bindResource(getSessionFactory(), sessionHolder);
|
||||
|
||||
AsyncRequestInterceptor asyncRequestInterceptor =
|
||||
new AsyncRequestInterceptor(getSessionFactory(), sessionHolder);
|
||||
asyncManager.registerCallableInterceptor(participateAttributeName, asyncRequestInterceptor);
|
||||
asyncManager.registerDeferredResultInterceptor(participateAttributeName, asyncRequestInterceptor);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postHandle(WebRequest request, ModelMap model) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Unbind the Hibernate {@code Session} from the thread and close it).
|
||||
* @see org.springframework.transaction.support.TransactionSynchronizationManager
|
||||
*/
|
||||
@Override
|
||||
public void afterCompletion(WebRequest request, Exception ex) throws DataAccessException {
|
||||
if (!decrementParticipateCount(request)) {
|
||||
SessionHolder sessionHolder =
|
||||
(SessionHolder) TransactionSynchronizationManager.unbindResource(getSessionFactory());
|
||||
logger.debug("Closing Hibernate Session in OpenSessionInViewInterceptor");
|
||||
SessionFactoryUtils.closeSession(sessionHolder.getSession());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private boolean decrementParticipateCount(WebRequest request) {
|
||||
String participateAttributeName = getParticipateAttributeName();
|
||||
Integer count = (Integer) request.getAttribute(participateAttributeName, WebRequest.SCOPE_REQUEST);
|
||||
if (count == null) {
|
||||
return false;
|
||||
}
|
||||
// Do not modify the Session: just clear the marker.
|
||||
if (count > 1) {
|
||||
request.setAttribute(participateAttributeName, count - 1, WebRequest.SCOPE_REQUEST);
|
||||
}
|
||||
else {
|
||||
request.removeAttribute(participateAttributeName, WebRequest.SCOPE_REQUEST);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterConcurrentHandlingStarted(WebRequest request) {
|
||||
if (!decrementParticipateCount(request)) {
|
||||
TransactionSynchronizationManager.unbindResource(getSessionFactory());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a Session for the SessionFactory that this interceptor uses.
|
||||
* <p>The default implementation delegates to the {@link SessionFactory#openSession}
|
||||
* method and sets the {@link Session}'s flush mode to "MANUAL".
|
||||
* @return the Session to use
|
||||
* @throws DataAccessResourceFailureException if the Session could not be created
|
||||
* @see org.hibernate.FlushMode#MANUAL
|
||||
*/
|
||||
protected Session openSession() throws DataAccessResourceFailureException {
|
||||
try {
|
||||
Session session = getSessionFactory().openSession();
|
||||
session.setFlushMode(FlushMode.MANUAL);
|
||||
return session;
|
||||
}
|
||||
catch (HibernateException ex) {
|
||||
throw new DataAccessResourceFailureException("Could not open Hibernate Session", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the request attribute that identifies that a request is
|
||||
* already intercepted.
|
||||
* <p>The default implementation takes the {@code toString()} representation
|
||||
* of the {@code SessionFactory} instance and appends {@link #PARTICIPATE_SUFFIX}.
|
||||
*/
|
||||
protected String getParticipateAttributeName() {
|
||||
return getSessionFactory().toString() + PARTICIPATE_SUFFIX;
|
||||
}
|
||||
|
||||
private boolean applySessionBindingInterceptor(WebAsyncManager asyncManager, String key) {
|
||||
if (asyncManager.getCallableInterceptor(key) == null) {
|
||||
return false;
|
||||
}
|
||||
((AsyncRequestInterceptor) asyncManager.getCallableInterceptor(key)).bindSession();
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,116 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate4.support;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.hibernate.FlushMode;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.dao.DataAccessResourceFailureException;
|
||||
import org.springframework.orm.hibernate4.SessionFactoryUtils;
|
||||
import org.springframework.orm.hibernate4.SessionHolder;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
|
||||
/**
|
||||
* Simple AOP Alliance {@link MethodInterceptor} implementation that binds a new
|
||||
* Hibernate {@link Session} for each method invocation, if none bound before.
|
||||
*
|
||||
* <p>This is a simple Hibernate Session scoping interceptor along the lines of
|
||||
* {@link OpenSessionInViewInterceptor}, just for use with AOP setup instead of
|
||||
* MVC setup. It opens a new {@link Session} with flush mode "MANUAL" since the
|
||||
* Session is only meant for reading, except when participating in a transaction.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.0.2
|
||||
* @see OpenSessionInViewInterceptor
|
||||
* @see OpenSessionInViewFilter
|
||||
* @see org.springframework.orm.hibernate4.HibernateTransactionManager
|
||||
* @see org.springframework.transaction.support.TransactionSynchronizationManager
|
||||
* @see org.hibernate.SessionFactory#getCurrentSession()
|
||||
*/
|
||||
public class OpenSessionInterceptor implements MethodInterceptor, InitializingBean {
|
||||
|
||||
private SessionFactory sessionFactory;
|
||||
|
||||
|
||||
/**
|
||||
* Set the Hibernate SessionFactory that should be used to create Hibernate Sessions.
|
||||
*/
|
||||
public void setSessionFactory(SessionFactory sessionFactory) {
|
||||
this.sessionFactory = sessionFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Hibernate SessionFactory that should be used to create Hibernate Sessions.
|
||||
*/
|
||||
public SessionFactory getSessionFactory() {
|
||||
return this.sessionFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
if (getSessionFactory() == null) {
|
||||
throw new IllegalArgumentException("Property 'sessionFactory' is required");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object invoke(MethodInvocation invocation) throws Throwable {
|
||||
SessionFactory sf = getSessionFactory();
|
||||
if (!TransactionSynchronizationManager.hasResource(sf)) {
|
||||
// New Session to be bound for the current method's scope...
|
||||
Session session = openSession();
|
||||
try {
|
||||
TransactionSynchronizationManager.bindResource(sf, new SessionHolder(session));
|
||||
return invocation.proceed();
|
||||
}
|
||||
finally {
|
||||
SessionFactoryUtils.closeSession(session);
|
||||
TransactionSynchronizationManager.unbindResource(sf);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Pre-bound Session found -> simply proceed.
|
||||
return invocation.proceed();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a Session for the SessionFactory that this interceptor uses.
|
||||
* <p>The default implementation delegates to the {@link SessionFactory#openSession}
|
||||
* method and sets the {@link Session}'s flush mode to "MANUAL".
|
||||
* @return the Session to use
|
||||
* @throws DataAccessResourceFailureException if the Session could not be created
|
||||
* @see org.hibernate.FlushMode#MANUAL
|
||||
*/
|
||||
protected Session openSession() throws DataAccessResourceFailureException {
|
||||
try {
|
||||
Session session = getSessionFactory().openSession();
|
||||
session.setFlushMode(FlushMode.MANUAL);
|
||||
return session;
|
||||
}
|
||||
catch (HibernateException ex) {
|
||||
throw new DataAccessResourceFailureException("Could not open Hibernate Session", ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
/**
|
||||
* Classes supporting the {@code org.springframework.orm.hibernate4} package.
|
||||
*/
|
||||
package org.springframework.orm.hibernate4.support;
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -1,270 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.jpa.jpa21;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.persistence.EntityTransaction;
|
||||
import javax.persistence.PersistenceContext;
|
||||
import javax.persistence.PersistenceContextType;
|
||||
import javax.persistence.SynchronizationType;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.orm.jpa.JpaTransactionManager;
|
||||
import org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.BDDMockito.*;
|
||||
|
||||
/**
|
||||
* Copy of {@link org.springframework.orm.jpa.support.PersistenceContextTransactionTests},
|
||||
* here to be tested against JPA 2.1, including unsynchronized persistence contexts.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.1.2
|
||||
*/
|
||||
public class PersistenceContextTransactionTests {
|
||||
|
||||
private EntityManagerFactory factory;
|
||||
|
||||
private EntityManager manager;
|
||||
|
||||
private EntityTransaction tx;
|
||||
|
||||
private TransactionTemplate tt;
|
||||
|
||||
private EntityManagerHoldingBean bean;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
factory = mock(EntityManagerFactory.class);
|
||||
manager = mock(EntityManager.class);
|
||||
tx = mock(EntityTransaction.class);
|
||||
|
||||
JpaTransactionManager tm = new JpaTransactionManager(factory);
|
||||
tt = new TransactionTemplate(tm);
|
||||
|
||||
given(factory.createEntityManager()).willReturn(manager);
|
||||
given(manager.getTransaction()).willReturn(tx);
|
||||
given(manager.isOpen()).willReturn(true);
|
||||
|
||||
bean = new EntityManagerHoldingBean();
|
||||
@SuppressWarnings("serial")
|
||||
PersistenceAnnotationBeanPostProcessor pabpp = new PersistenceAnnotationBeanPostProcessor() {
|
||||
@Override
|
||||
protected EntityManagerFactory findEntityManagerFactory(String unitName, String requestingBeanName) {
|
||||
return factory;
|
||||
}
|
||||
};
|
||||
pabpp.postProcessPropertyValues(null, null, bean, "bean");
|
||||
|
||||
assertTrue(TransactionSynchronizationManager.getResourceMap().isEmpty());
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
assertTrue(TransactionSynchronizationManager.getResourceMap().isEmpty());
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testTransactionCommitWithSharedEntityManager() {
|
||||
given(manager.getTransaction()).willReturn(tx);
|
||||
|
||||
tt.execute(status -> {
|
||||
bean.sharedEntityManager.flush();
|
||||
return null;
|
||||
});
|
||||
|
||||
verify(tx).commit();
|
||||
verify(manager).flush();
|
||||
verify(manager).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionCommitWithSharedEntityManagerAndPropagationSupports() {
|
||||
given(manager.isOpen()).willReturn(true);
|
||||
|
||||
tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
|
||||
|
||||
tt.execute(status -> {
|
||||
bean.sharedEntityManager.clear();
|
||||
return null;
|
||||
});
|
||||
|
||||
verify(manager).clear();
|
||||
verify(manager).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionCommitWithExtendedEntityManager() {
|
||||
given(manager.getTransaction()).willReturn(tx);
|
||||
|
||||
tt.execute(status -> {
|
||||
bean.extendedEntityManager.flush();
|
||||
return null;
|
||||
});
|
||||
|
||||
verify(tx, times(2)).commit();
|
||||
verify(manager).flush();
|
||||
verify(manager).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionCommitWithExtendedEntityManagerAndPropagationSupports() {
|
||||
given(manager.isOpen()).willReturn(true);
|
||||
|
||||
tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
|
||||
|
||||
tt.execute(status -> {
|
||||
bean.extendedEntityManager.flush();
|
||||
return null;
|
||||
});
|
||||
|
||||
verify(manager).flush();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionCommitWithSharedEntityManagerUnsynchronized() {
|
||||
given(manager.getTransaction()).willReturn(tx);
|
||||
|
||||
tt.execute(status -> {
|
||||
bean.sharedEntityManagerUnsynchronized.flush();
|
||||
return null;
|
||||
});
|
||||
|
||||
verify(tx).commit();
|
||||
verify(manager).flush();
|
||||
verify(manager, times(2)).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionCommitWithSharedEntityManagerUnsynchronizedAndPropagationSupports() {
|
||||
given(manager.isOpen()).willReturn(true);
|
||||
|
||||
tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
|
||||
|
||||
tt.execute(status -> {
|
||||
bean.sharedEntityManagerUnsynchronized.clear();
|
||||
return null;
|
||||
});
|
||||
|
||||
verify(manager).clear();
|
||||
verify(manager).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionCommitWithExtendedEntityManagerUnsynchronized() {
|
||||
given(manager.getTransaction()).willReturn(tx);
|
||||
|
||||
tt.execute(status -> {
|
||||
bean.extendedEntityManagerUnsynchronized.flush();
|
||||
return null;
|
||||
});
|
||||
|
||||
verify(tx).commit();
|
||||
verify(manager).flush();
|
||||
verify(manager).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionCommitWithExtendedEntityManagerUnsynchronizedAndPropagationSupports() {
|
||||
given(manager.isOpen()).willReturn(true);
|
||||
|
||||
tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
|
||||
|
||||
tt.execute(status -> {
|
||||
bean.extendedEntityManagerUnsynchronized.flush();
|
||||
return null;
|
||||
});
|
||||
|
||||
verify(manager).flush();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionCommitWithSharedEntityManagerUnsynchronizedJoined() {
|
||||
given(manager.getTransaction()).willReturn(tx);
|
||||
|
||||
tt.execute(status -> {
|
||||
bean.sharedEntityManagerUnsynchronized.joinTransaction();
|
||||
bean.sharedEntityManagerUnsynchronized.flush();
|
||||
return null;
|
||||
});
|
||||
|
||||
verify(tx).commit();
|
||||
verify(manager).flush();
|
||||
verify(manager, times(2)).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionCommitWithExtendedEntityManagerUnsynchronizedJoined() {
|
||||
given(manager.getTransaction()).willReturn(tx);
|
||||
|
||||
tt.execute(status -> {
|
||||
bean.extendedEntityManagerUnsynchronized.joinTransaction();
|
||||
bean.extendedEntityManagerUnsynchronized.flush();
|
||||
return null;
|
||||
});
|
||||
|
||||
verify(tx, times(2)).commit();
|
||||
verify(manager).flush();
|
||||
verify(manager).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionCommitWithExtendedEntityManagerUnsynchronizedJoinedAndPropagationSupports() {
|
||||
given(manager.isOpen()).willReturn(true);
|
||||
|
||||
tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
|
||||
|
||||
tt.execute(status -> {
|
||||
bean.extendedEntityManagerUnsynchronized.joinTransaction();
|
||||
bean.extendedEntityManagerUnsynchronized.flush();
|
||||
return null;
|
||||
});
|
||||
|
||||
verify(manager).flush();
|
||||
}
|
||||
|
||||
|
||||
public static class EntityManagerHoldingBean {
|
||||
|
||||
@PersistenceContext
|
||||
public EntityManager sharedEntityManager;
|
||||
|
||||
@PersistenceContext(type = PersistenceContextType.EXTENDED)
|
||||
public EntityManager extendedEntityManager;
|
||||
|
||||
@PersistenceContext(synchronization = SynchronizationType.UNSYNCHRONIZED)
|
||||
public EntityManager sharedEntityManagerUnsynchronized;
|
||||
|
||||
@PersistenceContext(type = PersistenceContextType.EXTENDED, synchronization = SynchronizationType.UNSYNCHRONIZED)
|
||||
public EntityManager extendedEntityManagerUnsynchronized;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,166 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.validation.hibernatevalidator5;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.context.annotation.CommonAnnotationBeanPostProcessor;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.tests.sample.beans.TestBean;
|
||||
import org.springframework.validation.beanvalidation.BeanValidationPostProcessor;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Copy of {@link org.springframework.validation.beanvalidation.BeanValidationPostProcessor},
|
||||
* here to be tested against Hibernate Validator 5.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.1
|
||||
*/
|
||||
public class BeanValidationPostProcessorTests {
|
||||
|
||||
@Test
|
||||
public void testNotNullConstraint() {
|
||||
GenericApplicationContext ac = new GenericApplicationContext();
|
||||
ac.registerBeanDefinition("bvpp", new RootBeanDefinition(BeanValidationPostProcessor.class));
|
||||
ac.registerBeanDefinition("capp", new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class));
|
||||
ac.registerBeanDefinition("bean", new RootBeanDefinition(NotNullConstrainedBean.class));
|
||||
try {
|
||||
ac.refresh();
|
||||
fail("Should have thrown BeanCreationException");
|
||||
}
|
||||
catch (BeanCreationException ex) {
|
||||
assertTrue(ex.getRootCause().getMessage().contains("testBean"));
|
||||
assertTrue(ex.getRootCause().getMessage().contains("invalid"));
|
||||
}
|
||||
ac.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotNullConstraintSatisfied() {
|
||||
GenericApplicationContext ac = new GenericApplicationContext();
|
||||
ac.registerBeanDefinition("bvpp", new RootBeanDefinition(BeanValidationPostProcessor.class));
|
||||
ac.registerBeanDefinition("capp", new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class));
|
||||
RootBeanDefinition bd = new RootBeanDefinition(NotNullConstrainedBean.class);
|
||||
bd.getPropertyValues().add("testBean", new TestBean());
|
||||
ac.registerBeanDefinition("bean", bd);
|
||||
ac.refresh();
|
||||
ac.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotNullConstraintAfterInitialization() {
|
||||
GenericApplicationContext ac = new GenericApplicationContext();
|
||||
RootBeanDefinition bvpp = new RootBeanDefinition(BeanValidationPostProcessor.class);
|
||||
bvpp.getPropertyValues().add("afterInitialization", true);
|
||||
ac.registerBeanDefinition("bvpp", bvpp);
|
||||
ac.registerBeanDefinition("capp", new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class));
|
||||
ac.registerBeanDefinition("bean", new RootBeanDefinition(AfterInitConstraintBean.class));
|
||||
ac.refresh();
|
||||
ac.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSizeConstraint() {
|
||||
GenericApplicationContext ac = new GenericApplicationContext();
|
||||
ac.registerBeanDefinition("bvpp", new RootBeanDefinition(BeanValidationPostProcessor.class));
|
||||
RootBeanDefinition bd = new RootBeanDefinition(NotNullConstrainedBean.class);
|
||||
bd.getPropertyValues().add("testBean", new TestBean());
|
||||
bd.getPropertyValues().add("stringValue", "s");
|
||||
ac.registerBeanDefinition("bean", bd);
|
||||
try {
|
||||
ac.refresh();
|
||||
fail("Should have thrown BeanCreationException");
|
||||
}
|
||||
catch (BeanCreationException ex) {
|
||||
assertTrue(ex.getRootCause().getMessage().contains("stringValue"));
|
||||
assertTrue(ex.getRootCause().getMessage().contains("invalid"));
|
||||
}
|
||||
ac.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSizeConstraintSatisfied() {
|
||||
GenericApplicationContext ac = new GenericApplicationContext();
|
||||
ac.registerBeanDefinition("bvpp", new RootBeanDefinition(BeanValidationPostProcessor.class));
|
||||
RootBeanDefinition bd = new RootBeanDefinition(NotNullConstrainedBean.class);
|
||||
bd.getPropertyValues().add("testBean", new TestBean());
|
||||
bd.getPropertyValues().add("stringValue", "ss");
|
||||
ac.registerBeanDefinition("bean", bd);
|
||||
ac.refresh();
|
||||
ac.close();
|
||||
}
|
||||
|
||||
|
||||
public static class NotNullConstrainedBean {
|
||||
|
||||
@NotNull
|
||||
private TestBean testBean;
|
||||
|
||||
@Size(min = 2)
|
||||
private String stringValue;
|
||||
|
||||
public TestBean getTestBean() {
|
||||
return testBean;
|
||||
}
|
||||
|
||||
public void setTestBean(TestBean testBean) {
|
||||
this.testBean = testBean;
|
||||
}
|
||||
|
||||
public String getStringValue() {
|
||||
return stringValue;
|
||||
}
|
||||
|
||||
public void setStringValue(String stringValue) {
|
||||
this.stringValue = stringValue;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
assertNotNull("Shouldn't be here after constraint checking", this.testBean);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class AfterInitConstraintBean {
|
||||
|
||||
@NotNull
|
||||
private TestBean testBean;
|
||||
|
||||
public TestBean getTestBean() {
|
||||
return testBean;
|
||||
}
|
||||
|
||||
public void setTestBean(TestBean testBean) {
|
||||
this.testBean = testBean;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
this.testBean = new TestBean();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,173 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.validation.hibernatevalidator5;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import javax.validation.constraints.Max;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.groups.Default;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.beans.MutablePropertyValues;
|
||||
import org.springframework.context.support.StaticApplicationContext;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.scheduling.annotation.AsyncAnnotationAdvisor;
|
||||
import org.springframework.scheduling.annotation.AsyncAnnotationBeanPostProcessor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.validation.beanvalidation.MethodValidationInterceptor;
|
||||
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Copy of {@link org.springframework.validation.beanvalidation.MethodValidationTests},
|
||||
* here to be tested against Hibernate Validator 5.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.1
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public class MethodValidationTests {
|
||||
|
||||
@Test
|
||||
public void testMethodValidationInterceptor() {
|
||||
MyValidBean bean = new MyValidBean();
|
||||
ProxyFactory proxyFactory = new ProxyFactory(bean);
|
||||
proxyFactory.addAdvice(new MethodValidationInterceptor());
|
||||
proxyFactory.addAdvisor(new AsyncAnnotationAdvisor());
|
||||
doTestProxyValidation((MyValidInterface) proxyFactory.getProxy());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMethodValidationPostProcessor() {
|
||||
StaticApplicationContext ac = new StaticApplicationContext();
|
||||
ac.registerSingleton("mvpp", MethodValidationPostProcessor.class);
|
||||
MutablePropertyValues pvs = new MutablePropertyValues();
|
||||
pvs.add("beforeExistingAdvisors", false);
|
||||
ac.registerSingleton("aapp", AsyncAnnotationBeanPostProcessor.class, pvs);
|
||||
ac.registerSingleton("bean", MyValidBean.class);
|
||||
ac.refresh();
|
||||
doTestProxyValidation(ac.getBean("bean", MyValidInterface.class));
|
||||
ac.close();
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void doTestProxyValidation(MyValidInterface proxy) {
|
||||
assertNotNull(proxy.myValidMethod("value", 5));
|
||||
try {
|
||||
assertNotNull(proxy.myValidMethod("value", 15));
|
||||
fail("Should have thrown ValidationException");
|
||||
}
|
||||
catch (javax.validation.ValidationException ex) {
|
||||
// expected
|
||||
}
|
||||
try {
|
||||
assertNotNull(proxy.myValidMethod(null, 5));
|
||||
fail("Should have thrown ValidationException");
|
||||
}
|
||||
catch (javax.validation.ValidationException ex) {
|
||||
// expected
|
||||
}
|
||||
try {
|
||||
assertNotNull(proxy.myValidMethod("value", 0));
|
||||
fail("Should have thrown ValidationException");
|
||||
}
|
||||
catch (javax.validation.ValidationException ex) {
|
||||
// expected
|
||||
}
|
||||
|
||||
proxy.myValidAsyncMethod("value", 5);
|
||||
try {
|
||||
proxy.myValidAsyncMethod("value", 15);
|
||||
fail("Should have thrown ValidationException");
|
||||
}
|
||||
catch (javax.validation.ValidationException ex) {
|
||||
// expected
|
||||
}
|
||||
try {
|
||||
proxy.myValidAsyncMethod(null, 5);
|
||||
fail("Should have thrown ValidationException");
|
||||
}
|
||||
catch (javax.validation.ValidationException ex) {
|
||||
// expected
|
||||
}
|
||||
|
||||
assertEquals("myValue", proxy.myGenericMethod("myValue"));
|
||||
try {
|
||||
proxy.myGenericMethod(null);
|
||||
fail("Should have thrown ValidationException");
|
||||
}
|
||||
catch (javax.validation.ValidationException ex) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@MyStereotype
|
||||
public static class MyValidBean implements MyValidInterface<String> {
|
||||
|
||||
@Override
|
||||
public Object myValidMethod(String arg1, int arg2) {
|
||||
return (arg2 == 0 ? null : "value");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void myValidAsyncMethod(String arg1, int arg2) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String myGenericMethod(String value) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public interface MyValidInterface<T> {
|
||||
|
||||
@NotNull Object myValidMethod(@NotNull(groups = MyGroup.class) String arg1, @Max(10) int arg2);
|
||||
|
||||
@MyValid
|
||||
@Async void myValidAsyncMethod(@NotNull(groups = OtherGroup.class) String arg1, @Max(10) int arg2);
|
||||
|
||||
T myGenericMethod(@NotNull T value);
|
||||
}
|
||||
|
||||
|
||||
public interface MyGroup {
|
||||
}
|
||||
|
||||
|
||||
public interface OtherGroup {
|
||||
}
|
||||
|
||||
|
||||
@Validated({MyGroup.class, Default.class})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface MyStereotype {
|
||||
}
|
||||
|
||||
|
||||
@Validated({OtherGroup.class, Default.class})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface MyValid {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,430 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.validation.hibernatevalidator5;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import javax.validation.Constraint;
|
||||
import javax.validation.ConstraintValidator;
|
||||
import javax.validation.ConstraintValidatorContext;
|
||||
import javax.validation.ConstraintViolation;
|
||||
import javax.validation.Payload;
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
import org.hibernate.validator.HibernateValidator;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.validation.BeanPropertyBindingResult;
|
||||
import org.springframework.validation.Errors;
|
||||
import org.springframework.validation.FieldError;
|
||||
import org.springframework.validation.ObjectError;
|
||||
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Copy of {@link org.springframework.validation.beanvalidation.ValidatorFactoryTests},
|
||||
* here to be tested against Hibernate Validator 5.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.1
|
||||
*/
|
||||
public class ValidatorFactoryTests {
|
||||
|
||||
@Test
|
||||
public void testSimpleValidation() throws Exception {
|
||||
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||
validator.afterPropertiesSet();
|
||||
|
||||
ValidPerson person = new ValidPerson();
|
||||
Set<ConstraintViolation<ValidPerson>> result = validator.validate(person);
|
||||
assertEquals(2, result.size());
|
||||
for (ConstraintViolation<ValidPerson> cv : result) {
|
||||
String path = cv.getPropertyPath().toString();
|
||||
if ("name".equals(path) || "address.street".equals(path)) {
|
||||
assertTrue(cv.getConstraintDescriptor().getAnnotation() instanceof NotNull);
|
||||
}
|
||||
else {
|
||||
fail("Invalid constraint violation with path '" + path + "'");
|
||||
}
|
||||
}
|
||||
validator.destroy();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleValidationWithCustomProvider() throws Exception {
|
||||
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||
validator.setProviderClass(HibernateValidator.class);
|
||||
validator.afterPropertiesSet();
|
||||
|
||||
ValidPerson person = new ValidPerson();
|
||||
Set<ConstraintViolation<ValidPerson>> result = validator.validate(person);
|
||||
assertEquals(2, result.size());
|
||||
for (ConstraintViolation<ValidPerson> cv : result) {
|
||||
String path = cv.getPropertyPath().toString();
|
||||
if ("name".equals(path) || "address.street".equals(path)) {
|
||||
assertTrue(cv.getConstraintDescriptor().getAnnotation() instanceof NotNull);
|
||||
}
|
||||
else {
|
||||
fail("Invalid constraint violation with path '" + path + "'");
|
||||
}
|
||||
}
|
||||
validator.destroy();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleValidationWithClassLevel() throws Exception {
|
||||
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||
validator.afterPropertiesSet();
|
||||
ValidPerson person = new ValidPerson();
|
||||
person.setName("Juergen");
|
||||
person.getAddress().setStreet("Juergen's Street");
|
||||
Set<ConstraintViolation<ValidPerson>> result = validator.validate(person);
|
||||
assertEquals(1, result.size());
|
||||
Iterator<ConstraintViolation<ValidPerson>> iterator = result.iterator();
|
||||
ConstraintViolation<?> cv = iterator.next();
|
||||
assertEquals("", cv.getPropertyPath().toString());
|
||||
assertTrue(cv.getConstraintDescriptor().getAnnotation() instanceof NameAddressValid);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpringValidationFieldType() throws Exception {
|
||||
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||
validator.afterPropertiesSet();
|
||||
|
||||
ValidPerson person = new ValidPerson();
|
||||
person.setName("Phil");
|
||||
person.getAddress().setStreet("Phil's Street");
|
||||
BeanPropertyBindingResult errors = new BeanPropertyBindingResult(person, "person");
|
||||
validator.validate(person, errors);
|
||||
assertEquals(1, errors.getErrorCount());
|
||||
assertThat("Field/Value type mismatch", errors.getFieldError("address").getRejectedValue(),
|
||||
instanceOf(ValidAddress.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpringValidation() throws Exception {
|
||||
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||
validator.afterPropertiesSet();
|
||||
|
||||
ValidPerson person = new ValidPerson();
|
||||
BeanPropertyBindingResult result = new BeanPropertyBindingResult(person, "person");
|
||||
validator.validate(person, result);
|
||||
assertEquals(2, result.getErrorCount());
|
||||
FieldError fieldError = result.getFieldError("name");
|
||||
assertEquals("name", fieldError.getField());
|
||||
List<String> errorCodes = Arrays.asList(fieldError.getCodes());
|
||||
assertEquals(4, errorCodes.size());
|
||||
assertTrue(errorCodes.contains("NotNull.person.name"));
|
||||
assertTrue(errorCodes.contains("NotNull.name"));
|
||||
assertTrue(errorCodes.contains("NotNull.java.lang.String"));
|
||||
assertTrue(errorCodes.contains("NotNull"));
|
||||
fieldError = result.getFieldError("address.street");
|
||||
assertEquals("address.street", fieldError.getField());
|
||||
errorCodes = Arrays.asList(fieldError.getCodes());
|
||||
assertEquals(5, errorCodes.size());
|
||||
assertTrue(errorCodes.contains("NotNull.person.address.street"));
|
||||
assertTrue(errorCodes.contains("NotNull.address.street"));
|
||||
assertTrue(errorCodes.contains("NotNull.street"));
|
||||
assertTrue(errorCodes.contains("NotNull.java.lang.String"));
|
||||
assertTrue(errorCodes.contains("NotNull"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpringValidationWithClassLevel() throws Exception {
|
||||
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||
validator.afterPropertiesSet();
|
||||
|
||||
ValidPerson person = new ValidPerson();
|
||||
person.setName("Juergen");
|
||||
person.getAddress().setStreet("Juergen's Street");
|
||||
BeanPropertyBindingResult result = new BeanPropertyBindingResult(person, "person");
|
||||
validator.validate(person, result);
|
||||
assertEquals(1, result.getErrorCount());
|
||||
ObjectError globalError = result.getGlobalError();
|
||||
List<String> errorCodes = Arrays.asList(globalError.getCodes());
|
||||
assertEquals(2, errorCodes.size());
|
||||
assertTrue(errorCodes.contains("NameAddressValid.person"));
|
||||
assertTrue(errorCodes.contains("NameAddressValid"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpringValidationWithAutowiredValidator() throws Exception {
|
||||
ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(
|
||||
LocalValidatorFactoryBean.class);
|
||||
LocalValidatorFactoryBean validator = ctx.getBean(LocalValidatorFactoryBean.class);
|
||||
|
||||
ValidPerson person = new ValidPerson();
|
||||
person.expectsAutowiredValidator = true;
|
||||
person.setName("Juergen");
|
||||
person.getAddress().setStreet("Juergen's Street");
|
||||
BeanPropertyBindingResult result = new BeanPropertyBindingResult(person, "person");
|
||||
validator.validate(person, result);
|
||||
assertEquals(1, result.getErrorCount());
|
||||
ObjectError globalError = result.getGlobalError();
|
||||
List<String> errorCodes = Arrays.asList(globalError.getCodes());
|
||||
assertEquals(2, errorCodes.size());
|
||||
assertTrue(errorCodes.contains("NameAddressValid.person"));
|
||||
assertTrue(errorCodes.contains("NameAddressValid"));
|
||||
ctx.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpringValidationWithErrorInListElement() throws Exception {
|
||||
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||
validator.afterPropertiesSet();
|
||||
|
||||
ValidPerson person = new ValidPerson();
|
||||
person.getAddressList().add(new ValidAddress());
|
||||
BeanPropertyBindingResult result = new BeanPropertyBindingResult(person, "person");
|
||||
validator.validate(person, result);
|
||||
assertEquals(3, result.getErrorCount());
|
||||
FieldError fieldError = result.getFieldError("name");
|
||||
assertEquals("name", fieldError.getField());
|
||||
fieldError = result.getFieldError("address.street");
|
||||
assertEquals("address.street", fieldError.getField());
|
||||
fieldError = result.getFieldError("addressList[0].street");
|
||||
assertEquals("addressList[0].street", fieldError.getField());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpringValidationWithErrorInSetElement() throws Exception {
|
||||
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||
validator.afterPropertiesSet();
|
||||
|
||||
ValidPerson person = new ValidPerson();
|
||||
person.getAddressSet().add(new ValidAddress());
|
||||
BeanPropertyBindingResult result = new BeanPropertyBindingResult(person, "person");
|
||||
validator.validate(person, result);
|
||||
assertEquals(3, result.getErrorCount());
|
||||
FieldError fieldError = result.getFieldError("name");
|
||||
assertEquals("name", fieldError.getField());
|
||||
fieldError = result.getFieldError("address.street");
|
||||
assertEquals("address.street", fieldError.getField());
|
||||
fieldError = result.getFieldError("addressSet[].street");
|
||||
assertEquals("addressSet[].street", fieldError.getField());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInnerBeanValidation() throws Exception {
|
||||
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||
validator.afterPropertiesSet();
|
||||
|
||||
MainBean mainBean = new MainBean();
|
||||
Errors errors = new BeanPropertyBindingResult(mainBean, "mainBean");
|
||||
validator.validate(mainBean, errors);
|
||||
Object rejected = errors.getFieldValue("inner.value");
|
||||
assertNull(rejected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidationWithOptionalField() throws Exception {
|
||||
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||
validator.afterPropertiesSet();
|
||||
|
||||
MainBeanWithOptional mainBean = new MainBeanWithOptional();
|
||||
Errors errors = new BeanPropertyBindingResult(mainBean, "mainBean");
|
||||
validator.validate(mainBean, errors);
|
||||
Object rejected = errors.getFieldValue("inner.value");
|
||||
assertNull(rejected);
|
||||
}
|
||||
|
||||
|
||||
@NameAddressValid
|
||||
public static class ValidPerson {
|
||||
|
||||
@NotNull
|
||||
private String name;
|
||||
|
||||
@Valid
|
||||
private ValidAddress address = new ValidAddress();
|
||||
|
||||
@Valid
|
||||
private List<ValidAddress> addressList = new LinkedList<ValidAddress>();
|
||||
|
||||
@Valid
|
||||
private Set<ValidAddress> addressSet = new LinkedHashSet<ValidAddress>();
|
||||
|
||||
public boolean expectsAutowiredValidator = false;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public ValidAddress getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public void setAddress(ValidAddress address) {
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
public List<ValidAddress> getAddressList() {
|
||||
return addressList;
|
||||
}
|
||||
|
||||
public void setAddressList(List<ValidAddress> addressList) {
|
||||
this.addressList = addressList;
|
||||
}
|
||||
|
||||
public Set<ValidAddress> getAddressSet() {
|
||||
return addressSet;
|
||||
}
|
||||
|
||||
public void setAddressSet(Set<ValidAddress> addressSet) {
|
||||
this.addressSet = addressSet;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class ValidAddress {
|
||||
|
||||
@NotNull
|
||||
private String street;
|
||||
|
||||
public String getStreet() {
|
||||
return street;
|
||||
}
|
||||
|
||||
public void setStreet(String street) {
|
||||
this.street = street;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Constraint(validatedBy = NameAddressValidator.class)
|
||||
public @interface NameAddressValid {
|
||||
|
||||
String message() default "Street must not contain name";
|
||||
|
||||
Class<?>[] groups() default {};
|
||||
|
||||
Class<?>[] payload() default {};
|
||||
}
|
||||
|
||||
|
||||
public static class NameAddressValidator implements ConstraintValidator<NameAddressValid, ValidPerson> {
|
||||
|
||||
@Autowired
|
||||
private Environment environment;
|
||||
|
||||
@Override
|
||||
public void initialize(NameAddressValid constraintAnnotation) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid(ValidPerson value, ConstraintValidatorContext context) {
|
||||
if (value.expectsAutowiredValidator) {
|
||||
assertNotNull(this.environment);
|
||||
}
|
||||
boolean valid = (value.name == null || !value.address.street.contains(value.name));
|
||||
if (!valid && "Phil".equals(value.name)) {
|
||||
context.buildConstraintViolationWithTemplate(
|
||||
context.getDefaultConstraintMessageTemplate()).addPropertyNode("address").addConstraintViolation().disableDefaultConstraintViolation();
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class MainBean {
|
||||
|
||||
@InnerValid
|
||||
private InnerBean inner = new InnerBean();
|
||||
|
||||
public InnerBean getInner() {
|
||||
return inner;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class MainBeanWithOptional {
|
||||
|
||||
@InnerValid
|
||||
private InnerBean inner = new InnerBean();
|
||||
|
||||
public Optional<InnerBean> getInner() {
|
||||
return Optional.ofNullable(inner);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class InnerBean {
|
||||
|
||||
private String value;
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
@Constraint(validatedBy=InnerValidator.class)
|
||||
public static @interface InnerValid {
|
||||
|
||||
String message() default "NOT VALID";
|
||||
|
||||
Class<?>[] groups() default { };
|
||||
|
||||
Class<? extends Payload>[] payload() default {};
|
||||
}
|
||||
|
||||
|
||||
public static class InnerValidator implements ConstraintValidator<InnerValid, InnerBean> {
|
||||
|
||||
@Override
|
||||
public void initialize(InnerValid constraintAnnotation) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid(InnerBean bean, ConstraintValidatorContext context) {
|
||||
context.disableDefaultConstraintViolation();
|
||||
if (bean.getValue() == null) {
|
||||
context.buildConstraintViolationWithTemplate("NULL").addPropertyNode("value").addConstraintViolation();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
log4j.appender.console=org.apache.log4j.ConsoleAppender
|
||||
log4j.appender.console.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.console.layout.ConversionPattern=%d{HH:mm:ss,SSS} [%c] - %m%n
|
||||
|
||||
log4j.rootCategory=WARN, console
|
||||
log4j.logger.org.springframework.beans=WARN
|
||||
log4j.logger.org.springframework.binding=DEBUG
|
||||
|
||||
#log4j.logger.org.springframework.orm.hibernate4=TRACE
|
||||
|
||||
|
|
@ -1,285 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate3;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.SessionFactory;
|
||||
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
/**
|
||||
* Abstract {@link org.springframework.beans.factory.FactoryBean} that creates
|
||||
* a Hibernate {@link org.hibernate.SessionFactory} within a Spring application
|
||||
* context, providing general infrastructure not related to Hibernate's
|
||||
* specific configuration API.
|
||||
*
|
||||
* <p>This class implements the
|
||||
* {@link org.springframework.dao.support.PersistenceExceptionTranslator}
|
||||
* interface, as autodetected by Spring's
|
||||
* {@link org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor},
|
||||
* for AOP-based translation of native exceptions to Spring DataAccessExceptions.
|
||||
* Hence, the presence of e.g. LocalSessionFactoryBean automatically enables
|
||||
* a PersistenceExceptionTranslationPostProcessor to translate Hibernate exceptions.
|
||||
*
|
||||
* <p>This class mainly serves as common base class for {@link LocalSessionFactoryBean}.
|
||||
* For details on typical SessionFactory setup, see the LocalSessionFactoryBean javadoc.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
* @see #setExposeTransactionAwareSessionFactory
|
||||
* @see org.hibernate.SessionFactory#getCurrentSession()
|
||||
* @see org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor
|
||||
* @deprecated as of Spring 4.3, in favor of Hibernate 4.x/5.x
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract class AbstractSessionFactoryBean extends HibernateExceptionTranslator
|
||||
implements FactoryBean<SessionFactory>, InitializingBean, DisposableBean {
|
||||
|
||||
/** Logger available to subclasses */
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private DataSource dataSource;
|
||||
|
||||
private boolean useTransactionAwareDataSource = false;
|
||||
|
||||
private boolean exposeTransactionAwareSessionFactory = true;
|
||||
|
||||
private SessionFactory sessionFactory;
|
||||
|
||||
|
||||
/**
|
||||
* Set the DataSource to be used by the SessionFactory.
|
||||
* If set, this will override corresponding settings in Hibernate properties.
|
||||
* <p>If this is set, the Hibernate settings should not define
|
||||
* a connection provider to avoid meaningless double configuration.
|
||||
* <p>If using HibernateTransactionManager as transaction strategy, consider
|
||||
* proxying your target DataSource with a LazyConnectionDataSourceProxy.
|
||||
* This defers fetching of an actual JDBC Connection until the first JDBC
|
||||
* Statement gets executed, even within JDBC transactions (as performed by
|
||||
* HibernateTransactionManager). Such lazy fetching is particularly beneficial
|
||||
* for read-only operations, in particular if the chances of resolving the
|
||||
* result in the second-level cache are high.
|
||||
* <p>As JTA and transactional JNDI DataSources already provide lazy enlistment
|
||||
* of JDBC Connections, LazyConnectionDataSourceProxy does not add value with
|
||||
* JTA (i.e. Spring's JtaTransactionManager) as transaction strategy.
|
||||
* @see #setUseTransactionAwareDataSource
|
||||
* @see HibernateTransactionManager
|
||||
* @see org.springframework.transaction.jta.JtaTransactionManager
|
||||
* @see org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy
|
||||
*/
|
||||
public void setDataSource(DataSource dataSource) {
|
||||
this.dataSource = dataSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the DataSource to be used by the SessionFactory.
|
||||
*/
|
||||
public DataSource getDataSource() {
|
||||
return this.dataSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether to use a transaction-aware DataSource for the SessionFactory,
|
||||
* i.e. whether to automatically wrap the passed-in DataSource with Spring's
|
||||
* TransactionAwareDataSourceProxy.
|
||||
* <p>Default is "false": LocalSessionFactoryBean is usually used with Spring's
|
||||
* HibernateTransactionManager or JtaTransactionManager, both of which work nicely
|
||||
* on a plain JDBC DataSource. Hibernate Sessions and their JDBC Connections are
|
||||
* fully managed by the Hibernate/JTA transaction infrastructure in such a scenario.
|
||||
* <p>If you switch this flag to "true", Spring's Hibernate access will be able to
|
||||
* <i>participate in JDBC-based transactions managed outside of Hibernate</i>
|
||||
* (for example, by Spring's DataSourceTransactionManager). This can be convenient
|
||||
* if you need a different local transaction strategy for another O/R mapping tool,
|
||||
* for example, but still want Hibernate access to join into those transactions.
|
||||
* <p>A further benefit of this option is that <i>plain Sessions opened directly
|
||||
* via the SessionFactory</i>, outside of Spring's Hibernate support, will still
|
||||
* participate in active Spring-managed transactions. However, consider using
|
||||
* Hibernate's {@code getCurrentSession()} method instead (see javadoc of
|
||||
* "exposeTransactionAwareSessionFactory" property).
|
||||
* <p><b>WARNING:</b> When using a transaction-aware JDBC DataSource in combination
|
||||
* with OpenSessionInViewFilter/Interceptor, whether participating in JTA or
|
||||
* external JDBC-based transactions, it is strongly recommended to set Hibernate's
|
||||
* Connection release mode to "after_transaction" or "after_statement", which
|
||||
* guarantees proper Connection handling in such a scenario. In contrast to that,
|
||||
* HibernateTransactionManager generally requires release mode "on_close".
|
||||
* <p>Note: If you want to use Hibernate's Connection release mode "after_statement"
|
||||
* with a DataSource specified on this LocalSessionFactoryBean (for example, a
|
||||
* JTA-aware DataSource fetched from JNDI), switch this setting to "true".
|
||||
* Otherwise, the ConnectionProvider used underneath will vote against aggressive
|
||||
* release and thus silently switch to release mode "after_transaction".
|
||||
* @see #setDataSource
|
||||
* @see #setExposeTransactionAwareSessionFactory
|
||||
* @see org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy
|
||||
* @see org.springframework.jdbc.datasource.DataSourceTransactionManager
|
||||
* @see org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
|
||||
* @see org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor
|
||||
* @see HibernateTransactionManager
|
||||
* @see org.springframework.transaction.jta.JtaTransactionManager
|
||||
*/
|
||||
public void setUseTransactionAwareDataSource(boolean useTransactionAwareDataSource) {
|
||||
this.useTransactionAwareDataSource = useTransactionAwareDataSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether to use a transaction-aware DataSource for the SessionFactory.
|
||||
*/
|
||||
protected boolean isUseTransactionAwareDataSource() {
|
||||
return this.useTransactionAwareDataSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether to expose a transaction-aware current Session from the
|
||||
* SessionFactory's {@code getCurrentSession()} method, returning the
|
||||
* Session that's associated with the current Spring-managed transaction, if any.
|
||||
* <p>Default is "true", letting data access code work with the plain
|
||||
* Hibernate SessionFactory and its {@code getCurrentSession()} method,
|
||||
* while still being able to participate in current Spring-managed transactions:
|
||||
* with any transaction management strategy, either local or JTA / EJB CMT,
|
||||
* and any transaction synchronization mechanism, either Spring or JTA.
|
||||
* Furthermore, {@code getCurrentSession()} will also seamlessly work with
|
||||
* a request-scoped Session managed by OpenSessionInViewFilter/Interceptor.
|
||||
* <p>Turn this flag off to expose the plain Hibernate SessionFactory with
|
||||
* Hibernate's default {@code getCurrentSession()} behavior, supporting
|
||||
* plain JTA synchronization only. Alternatively, simply override the
|
||||
* corresponding Hibernate property "hibernate.current_session_context_class".
|
||||
* @see SpringSessionContext
|
||||
* @see org.hibernate.SessionFactory#getCurrentSession()
|
||||
* @see org.springframework.transaction.jta.JtaTransactionManager
|
||||
* @see HibernateTransactionManager
|
||||
* @see org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
|
||||
* @see org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor
|
||||
*/
|
||||
public void setExposeTransactionAwareSessionFactory(boolean exposeTransactionAwareSessionFactory) {
|
||||
this.exposeTransactionAwareSessionFactory = exposeTransactionAwareSessionFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether to expose a transaction-aware proxy for the SessionFactory.
|
||||
*/
|
||||
protected boolean isExposeTransactionAwareSessionFactory() {
|
||||
return this.exposeTransactionAwareSessionFactory;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Build and expose the SessionFactory.
|
||||
* @see #buildSessionFactory()
|
||||
* @see #wrapSessionFactoryIfNecessary
|
||||
*/
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
SessionFactory rawSf = buildSessionFactory();
|
||||
this.sessionFactory = wrapSessionFactoryIfNecessary(rawSf);
|
||||
afterSessionFactoryCreation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap the given SessionFactory with a proxy, if demanded.
|
||||
* <p>The default implementation simply returns the given SessionFactory as-is.
|
||||
* Subclasses may override this to implement transaction awareness through
|
||||
* a SessionFactory proxy, for example.
|
||||
* @param rawSf the raw SessionFactory as built by {@link #buildSessionFactory()}
|
||||
* @return the SessionFactory reference to expose
|
||||
* @see #buildSessionFactory()
|
||||
*/
|
||||
protected SessionFactory wrapSessionFactoryIfNecessary(SessionFactory rawSf) {
|
||||
return rawSf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the exposed SessionFactory.
|
||||
* Will throw an exception if not initialized yet.
|
||||
* @return the SessionFactory (never {@code null})
|
||||
* @throws IllegalStateException if the SessionFactory has not been initialized yet
|
||||
*/
|
||||
protected final SessionFactory getSessionFactory() {
|
||||
if (this.sessionFactory == null) {
|
||||
throw new IllegalStateException("SessionFactory not initialized yet");
|
||||
}
|
||||
return this.sessionFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the SessionFactory on bean factory shutdown.
|
||||
*/
|
||||
@Override
|
||||
public void destroy() throws HibernateException {
|
||||
logger.info("Closing Hibernate SessionFactory");
|
||||
try {
|
||||
beforeSessionFactoryDestruction();
|
||||
}
|
||||
finally {
|
||||
this.sessionFactory.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the singleton SessionFactory.
|
||||
*/
|
||||
@Override
|
||||
public SessionFactory getObject() {
|
||||
return this.sessionFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends SessionFactory> getObjectType() {
|
||||
return (this.sessionFactory != null ? this.sessionFactory.getClass() : SessionFactory.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Build the underlying Hibernate SessionFactory.
|
||||
* @return the raw SessionFactory (potentially to be wrapped with a
|
||||
* transaction-aware proxy before it is exposed to the application)
|
||||
* @throws Exception in case of initialization failure
|
||||
*/
|
||||
protected abstract SessionFactory buildSessionFactory() throws Exception;
|
||||
|
||||
/**
|
||||
* Hook that allows post-processing after the SessionFactory has been
|
||||
* successfully created. The SessionFactory is already available through
|
||||
* {@code getSessionFactory()} at this point.
|
||||
* <p>This implementation is empty.
|
||||
* @throws Exception in case of initialization failure
|
||||
* @see #getSessionFactory()
|
||||
*/
|
||||
protected void afterSessionFactoryCreation() throws Exception {
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook that allows shutdown processing before the SessionFactory
|
||||
* will be closed. The SessionFactory is still available through
|
||||
* {@code getSessionFactory()} at this point.
|
||||
* <p>This implementation is empty.
|
||||
* @see #getSessionFactory()
|
||||
*/
|
||||
protected void beforeSessionFactoryDestruction() {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,145 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate3;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.engine.FilterDefinition;
|
||||
import org.hibernate.type.Type;
|
||||
import org.hibernate.type.TypeResolver;
|
||||
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
/**
|
||||
* Convenient FactoryBean for defining Hibernate FilterDefinitions.
|
||||
* Exposes a corresponding Hibernate FilterDefinition object.
|
||||
*
|
||||
* <p>Typically defined as an inner bean within a LocalSessionFactoryBean
|
||||
* definition, as the list element for the "filterDefinitions" bean property.
|
||||
* For example:
|
||||
*
|
||||
* <pre class="code">
|
||||
* <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
|
||||
* ...
|
||||
* <property name="filterDefinitions">
|
||||
* <list>
|
||||
* <bean class="org.springframework.orm.hibernate3.FilterDefinitionFactoryBean">
|
||||
* <property name="filterName" value="myFilter"/>
|
||||
* <property name="parameterTypes">
|
||||
* <map>
|
||||
* <entry key="myParam" value="string"/>
|
||||
* <entry key="myOtherParam" value="long"/>
|
||||
* </map>
|
||||
* </property>
|
||||
* </bean>
|
||||
* </list>
|
||||
* </property>
|
||||
* ...
|
||||
* </bean></pre>
|
||||
*
|
||||
* Alternatively, specify a bean id (or name) attribute for the inner bean,
|
||||
* instead of the "filterName" property.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @see org.hibernate.engine.FilterDefinition
|
||||
* @see LocalSessionFactoryBean#setFilterDefinitions
|
||||
* @deprecated as of Spring 4.3, in favor of Hibernate 4.x/5.x
|
||||
*/
|
||||
@Deprecated
|
||||
public class FilterDefinitionFactoryBean implements FactoryBean<FilterDefinition>, BeanNameAware, InitializingBean {
|
||||
|
||||
private final TypeResolver typeResolver = new TypeResolver();
|
||||
|
||||
private String filterName;
|
||||
|
||||
private Map<String, Type> parameterTypeMap = new HashMap<String, Type>();
|
||||
|
||||
private String defaultFilterCondition;
|
||||
|
||||
private FilterDefinition filterDefinition;
|
||||
|
||||
|
||||
/**
|
||||
* Set the name of the filter.
|
||||
*/
|
||||
public void setFilterName(String filterName) {
|
||||
this.filterName = filterName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the parameter types for the filter,
|
||||
* with parameter names as keys and type names as values.
|
||||
* See {@code org.hibernate.type.TypeResolver#heuristicType(String)}.
|
||||
*/
|
||||
public void setParameterTypes(Map<String, String> parameterTypes) {
|
||||
if (parameterTypes != null) {
|
||||
this.parameterTypeMap = new HashMap<String, Type>(parameterTypes.size());
|
||||
for (Map.Entry<String, String> entry : parameterTypes.entrySet()) {
|
||||
this.parameterTypeMap.put(entry.getKey(), this.typeResolver.heuristicType(entry.getValue()));
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.parameterTypeMap = new HashMap<String, Type>();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a default filter condition for the filter, if any.
|
||||
*/
|
||||
public void setDefaultFilterCondition(String defaultFilterCondition) {
|
||||
this.defaultFilterCondition = defaultFilterCondition;
|
||||
}
|
||||
|
||||
/**
|
||||
* If no explicit filter name has been specified, the bean name of
|
||||
* the FilterDefinitionFactoryBean will be used.
|
||||
* @see #setFilterName
|
||||
*/
|
||||
@Override
|
||||
public void setBeanName(String name) {
|
||||
if (this.filterName == null) {
|
||||
this.filterName = name;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
this.filterDefinition =
|
||||
new FilterDefinition(this.filterName, this.defaultFilterCondition, this.parameterTypeMap);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public FilterDefinition getObject() {
|
||||
return this.filterDefinition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<FilterDefinition> getObjectType() {
|
||||
return FilterDefinition.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,492 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate3;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.hibernate.FlushMode;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.Interceptor;
|
||||
import org.hibernate.JDBCException;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.exception.GenericJDBCException;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.core.Constants;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.jdbc.support.SQLExceptionTranslator;
|
||||
|
||||
/**
|
||||
* Base class for {@link HibernateTemplate} and {@link HibernateInterceptor},
|
||||
* defining common properties such as SessionFactory and flushing behavior.
|
||||
*
|
||||
* <p>Not intended to be used directly.
|
||||
* See {@link HibernateTemplate} and {@link HibernateInterceptor}.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @see HibernateTemplate
|
||||
* @see HibernateInterceptor
|
||||
* @see #setFlushMode
|
||||
* @deprecated as of Spring 4.3, in favor of Hibernate 4.x/5.x
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract class HibernateAccessor implements InitializingBean, BeanFactoryAware {
|
||||
|
||||
/**
|
||||
* Never flush is a good strategy for read-only units of work.
|
||||
* Hibernate will not track and look for changes in this case,
|
||||
* avoiding any overhead of modification detection.
|
||||
* <p>In case of an existing Session, FLUSH_NEVER will turn the flush mode
|
||||
* to NEVER for the scope of the current operation, resetting the previous
|
||||
* flush mode afterwards.
|
||||
* @see #setFlushMode
|
||||
*/
|
||||
public static final int FLUSH_NEVER = 0;
|
||||
|
||||
/**
|
||||
* Automatic flushing is the default mode for a Hibernate Session.
|
||||
* A session will get flushed on transaction commit, and on certain find
|
||||
* operations that might involve already modified instances, but not
|
||||
* after each unit of work like with eager flushing.
|
||||
* <p>In case of an existing Session, FLUSH_AUTO will participate in the
|
||||
* existing flush mode, not modifying it for the current operation.
|
||||
* This in particular means that this setting will not modify an existing
|
||||
* flush mode NEVER, in contrast to FLUSH_EAGER.
|
||||
* @see #setFlushMode
|
||||
*/
|
||||
public static final int FLUSH_AUTO = 1;
|
||||
|
||||
/**
|
||||
* Eager flushing leads to immediate synchronization with the database,
|
||||
* even if in a transaction. This causes inconsistencies to show up and throw
|
||||
* a respective exception immediately, and JDBC access code that participates
|
||||
* in the same transaction will see the changes as the database is already
|
||||
* aware of them then. But the drawbacks are:
|
||||
* <ul>
|
||||
* <li>additional communication roundtrips with the database, instead of a
|
||||
* single batch at transaction commit;
|
||||
* <li>the fact that an actual database rollback is needed if the Hibernate
|
||||
* transaction rolls back (due to already submitted SQL statements).
|
||||
* </ul>
|
||||
* <p>In case of an existing Session, FLUSH_EAGER will turn the flush mode
|
||||
* to AUTO for the scope of the current operation and issue a flush at the
|
||||
* end, resetting the previous flush mode afterwards.
|
||||
* @see #setFlushMode
|
||||
*/
|
||||
public static final int FLUSH_EAGER = 2;
|
||||
|
||||
/**
|
||||
* Flushing at commit only is intended for units of work where no
|
||||
* intermediate flushing is desired, not even for find operations
|
||||
* that might involve already modified instances.
|
||||
* <p>In case of an existing Session, FLUSH_COMMIT will turn the flush mode
|
||||
* to COMMIT for the scope of the current operation, resetting the previous
|
||||
* flush mode afterwards. The only exception is an existing flush mode
|
||||
* NEVER, which will not be modified through this setting.
|
||||
* @see #setFlushMode
|
||||
*/
|
||||
public static final int FLUSH_COMMIT = 3;
|
||||
|
||||
/**
|
||||
* Flushing before every query statement is rarely necessary.
|
||||
* It is only available for special needs.
|
||||
* <p>In case of an existing Session, FLUSH_ALWAYS will turn the flush mode
|
||||
* to ALWAYS for the scope of the current operation, resetting the previous
|
||||
* flush mode afterwards.
|
||||
* @see #setFlushMode
|
||||
*/
|
||||
public static final int FLUSH_ALWAYS = 4;
|
||||
|
||||
|
||||
/** Constants instance for HibernateAccessor */
|
||||
private static final Constants constants = new Constants(HibernateAccessor.class);
|
||||
|
||||
/** Logger available to subclasses */
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private SessionFactory sessionFactory;
|
||||
|
||||
private Object entityInterceptor;
|
||||
|
||||
private SQLExceptionTranslator jdbcExceptionTranslator;
|
||||
|
||||
private SQLExceptionTranslator defaultJdbcExceptionTranslator;
|
||||
|
||||
private int flushMode = FLUSH_AUTO;
|
||||
|
||||
private String[] filterNames;
|
||||
|
||||
/**
|
||||
* Just needed for entityInterceptorBeanName.
|
||||
* @see #setEntityInterceptorBeanName
|
||||
*/
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
|
||||
/**
|
||||
* Set the Hibernate SessionFactory that should be used to create
|
||||
* Hibernate Sessions.
|
||||
*/
|
||||
public void setSessionFactory(SessionFactory sessionFactory) {
|
||||
this.sessionFactory = sessionFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Hibernate SessionFactory that should be used to create
|
||||
* Hibernate Sessions.
|
||||
*/
|
||||
public SessionFactory getSessionFactory() {
|
||||
return this.sessionFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the bean name of a Hibernate entity interceptor that allows to inspect
|
||||
* and change property values before writing to and reading from the database.
|
||||
* Will get applied to any new Session created by this transaction manager.
|
||||
* <p>Requires the bean factory to be known, to be able to resolve the bean
|
||||
* name to an interceptor instance on session creation. Typically used for
|
||||
* prototype interceptors, i.e. a new interceptor instance per session.
|
||||
* <p>Can also be used for shared interceptor instances, but it is recommended
|
||||
* to set the interceptor reference directly in such a scenario.
|
||||
* @param entityInterceptorBeanName the name of the entity interceptor in
|
||||
* the bean factory
|
||||
* @see #setBeanFactory
|
||||
* @see #setEntityInterceptor
|
||||
*/
|
||||
public void setEntityInterceptorBeanName(String entityInterceptorBeanName) {
|
||||
this.entityInterceptor = entityInterceptorBeanName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a Hibernate entity interceptor that allows to inspect and change
|
||||
* property values before writing to and reading from the database.
|
||||
* Will get applied to any <b>new</b> Session created by this object.
|
||||
* <p>Such an interceptor can either be set at the SessionFactory level,
|
||||
* i.e. on LocalSessionFactoryBean, or at the Session level, i.e. on
|
||||
* HibernateTemplate, HibernateInterceptor, and HibernateTransactionManager.
|
||||
* It's preferable to set it on LocalSessionFactoryBean or HibernateTransactionManager
|
||||
* to avoid repeated configuration and guarantee consistent behavior in transactions.
|
||||
* @see #setEntityInterceptorBeanName
|
||||
* @see LocalSessionFactoryBean#setEntityInterceptor
|
||||
* @see HibernateTransactionManager#setEntityInterceptor
|
||||
*/
|
||||
public void setEntityInterceptor(Interceptor entityInterceptor) {
|
||||
this.entityInterceptor = entityInterceptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current Hibernate entity interceptor, or {@code null} if none.
|
||||
* Resolves an entity interceptor bean name via the bean factory,
|
||||
* if necessary.
|
||||
* @throws IllegalStateException if bean name specified but no bean factory set
|
||||
* @throws org.springframework.beans.BeansException if bean name resolution via the bean factory failed
|
||||
* @see #setEntityInterceptor
|
||||
* @see #setEntityInterceptorBeanName
|
||||
* @see #setBeanFactory
|
||||
*/
|
||||
public Interceptor getEntityInterceptor() throws IllegalStateException, BeansException {
|
||||
if (this.entityInterceptor instanceof String) {
|
||||
if (this.beanFactory == null) {
|
||||
throw new IllegalStateException("Cannot get entity interceptor via bean name if no bean factory set");
|
||||
}
|
||||
return this.beanFactory.getBean((String) this.entityInterceptor, Interceptor.class);
|
||||
}
|
||||
return (Interceptor) this.entityInterceptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the JDBC exception translator for this instance.
|
||||
* <p>Applied to any SQLException root cause of a Hibernate JDBCException,
|
||||
* overriding Hibernate's default SQLException translation (which is
|
||||
* based on Hibernate's Dialect for a specific target database).
|
||||
* @param jdbcExceptionTranslator the exception translator
|
||||
* @see java.sql.SQLException
|
||||
* @see org.hibernate.JDBCException
|
||||
* @see org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator
|
||||
* @see org.springframework.jdbc.support.SQLStateSQLExceptionTranslator
|
||||
*/
|
||||
public void setJdbcExceptionTranslator(SQLExceptionTranslator jdbcExceptionTranslator) {
|
||||
this.jdbcExceptionTranslator = jdbcExceptionTranslator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the JDBC exception translator for this instance, if any.
|
||||
*/
|
||||
public SQLExceptionTranslator getJdbcExceptionTranslator() {
|
||||
return this.jdbcExceptionTranslator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the flush behavior by the name of the respective constant
|
||||
* in this class, e.g. "FLUSH_AUTO". Default is "FLUSH_AUTO".
|
||||
* @param constantName name of the constant
|
||||
* @see #setFlushMode
|
||||
* @see #FLUSH_AUTO
|
||||
*/
|
||||
public void setFlushModeName(String constantName) {
|
||||
setFlushMode(constants.asNumber(constantName).intValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the flush behavior to one of the constants in this class.
|
||||
* Default is FLUSH_AUTO.
|
||||
* @see #setFlushModeName
|
||||
* @see #FLUSH_AUTO
|
||||
*/
|
||||
public void setFlushMode(int flushMode) {
|
||||
this.flushMode = flushMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return if a flush should be forced after executing the callback code.
|
||||
*/
|
||||
public int getFlushMode() {
|
||||
return this.flushMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name of a Hibernate filter to be activated for all
|
||||
* Sessions that this accessor works with.
|
||||
* <p>This filter will be enabled at the beginning of each operation
|
||||
* and correspondingly disabled at the end of the operation.
|
||||
* This will work for newly opened Sessions as well as for existing
|
||||
* Sessions (for example, within a transaction).
|
||||
* @see #enableFilters(org.hibernate.Session)
|
||||
* @see org.hibernate.Session#enableFilter(String)
|
||||
* @see LocalSessionFactoryBean#setFilterDefinitions
|
||||
*/
|
||||
public void setFilterName(String filter) {
|
||||
this.filterNames = new String[] {filter};
|
||||
}
|
||||
|
||||
/**
|
||||
* Set one or more names of Hibernate filters to be activated for all
|
||||
* Sessions that this accessor works with.
|
||||
* <p>Each of those filters will be enabled at the beginning of each
|
||||
* operation and correspondingly disabled at the end of the operation.
|
||||
* This will work for newly opened Sessions as well as for existing
|
||||
* Sessions (for example, within a transaction).
|
||||
* @see #enableFilters(org.hibernate.Session)
|
||||
* @see org.hibernate.Session#enableFilter(String)
|
||||
* @see LocalSessionFactoryBean#setFilterDefinitions
|
||||
*/
|
||||
public void setFilterNames(String... filterNames) {
|
||||
this.filterNames = filterNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the names of Hibernate filters to be activated, if any.
|
||||
*/
|
||||
public String[] getFilterNames() {
|
||||
return this.filterNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* The bean factory just needs to be known for resolving entity interceptor
|
||||
* bean names. It does not need to be set for any other mode of operation.
|
||||
* @see #setEntityInterceptorBeanName
|
||||
*/
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
if (getSessionFactory() == null) {
|
||||
throw new IllegalArgumentException("Property 'sessionFactory' is required");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Apply the flush mode that's been specified for this accessor
|
||||
* to the given Session.
|
||||
* @param session the current Hibernate Session
|
||||
* @param existingTransaction if executing within an existing transaction
|
||||
* @return the previous flush mode to restore after the operation,
|
||||
* or {@code null} if none
|
||||
* @see #setFlushMode
|
||||
* @see org.hibernate.Session#setFlushMode
|
||||
*/
|
||||
protected FlushMode applyFlushMode(Session session, boolean existingTransaction) {
|
||||
if (getFlushMode() == FLUSH_NEVER) {
|
||||
if (existingTransaction) {
|
||||
FlushMode previousFlushMode = session.getFlushMode();
|
||||
if (!previousFlushMode.lessThan(FlushMode.COMMIT)) {
|
||||
session.setFlushMode(FlushMode.MANUAL);
|
||||
return previousFlushMode;
|
||||
}
|
||||
}
|
||||
else {
|
||||
session.setFlushMode(FlushMode.MANUAL);
|
||||
}
|
||||
}
|
||||
else if (getFlushMode() == FLUSH_EAGER) {
|
||||
if (existingTransaction) {
|
||||
FlushMode previousFlushMode = session.getFlushMode();
|
||||
if (!previousFlushMode.equals(FlushMode.AUTO)) {
|
||||
session.setFlushMode(FlushMode.AUTO);
|
||||
return previousFlushMode;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// rely on default FlushMode.AUTO
|
||||
}
|
||||
}
|
||||
else if (getFlushMode() == FLUSH_COMMIT) {
|
||||
if (existingTransaction) {
|
||||
FlushMode previousFlushMode = session.getFlushMode();
|
||||
if (previousFlushMode.equals(FlushMode.AUTO) || previousFlushMode.equals(FlushMode.ALWAYS)) {
|
||||
session.setFlushMode(FlushMode.COMMIT);
|
||||
return previousFlushMode;
|
||||
}
|
||||
}
|
||||
else {
|
||||
session.setFlushMode(FlushMode.COMMIT);
|
||||
}
|
||||
}
|
||||
else if (getFlushMode() == FLUSH_ALWAYS) {
|
||||
if (existingTransaction) {
|
||||
FlushMode previousFlushMode = session.getFlushMode();
|
||||
if (!previousFlushMode.equals(FlushMode.ALWAYS)) {
|
||||
session.setFlushMode(FlushMode.ALWAYS);
|
||||
return previousFlushMode;
|
||||
}
|
||||
}
|
||||
else {
|
||||
session.setFlushMode(FlushMode.ALWAYS);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush the given Hibernate Session if necessary.
|
||||
* @param session the current Hibernate Session
|
||||
* @param existingTransaction if executing within an existing transaction
|
||||
* @throws HibernateException in case of Hibernate flushing errors
|
||||
*/
|
||||
protected void flushIfNecessary(Session session, boolean existingTransaction) throws HibernateException {
|
||||
if (getFlushMode() == FLUSH_EAGER || (!existingTransaction && getFlushMode() != FLUSH_NEVER)) {
|
||||
logger.debug("Eagerly flushing Hibernate session");
|
||||
session.flush();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert the given HibernateException to an appropriate exception
|
||||
* from the {@code org.springframework.dao} hierarchy.
|
||||
* <p>Will automatically apply a specified SQLExceptionTranslator to a
|
||||
* Hibernate JDBCException, else rely on Hibernate's default translation.
|
||||
* @param ex HibernateException that occured
|
||||
* @return a corresponding DataAccessException
|
||||
* @see SessionFactoryUtils#convertHibernateAccessException
|
||||
* @see #setJdbcExceptionTranslator
|
||||
*/
|
||||
public DataAccessException convertHibernateAccessException(HibernateException ex) {
|
||||
if (getJdbcExceptionTranslator() != null && ex instanceof JDBCException) {
|
||||
return convertJdbcAccessException((JDBCException) ex, getJdbcExceptionTranslator());
|
||||
}
|
||||
else if (GenericJDBCException.class == ex.getClass()) {
|
||||
return convertJdbcAccessException((GenericJDBCException) ex, getDefaultJdbcExceptionTranslator());
|
||||
}
|
||||
return SessionFactoryUtils.convertHibernateAccessException(ex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given Hibernate JDBCException to an appropriate exception
|
||||
* from the {@code org.springframework.dao} hierarchy, using the
|
||||
* given SQLExceptionTranslator.
|
||||
* @param ex Hibernate JDBCException that occured
|
||||
* @param translator the SQLExceptionTranslator to use
|
||||
* @return a corresponding DataAccessException
|
||||
*/
|
||||
protected DataAccessException convertJdbcAccessException(JDBCException ex, SQLExceptionTranslator translator) {
|
||||
return translator.translate("Hibernate operation: " + ex.getMessage(), ex.getSQL(), ex.getSQLException());
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given SQLException to an appropriate exception from the
|
||||
* {@code org.springframework.dao} hierarchy. Can be overridden in subclasses.
|
||||
* <p>Note that a direct SQLException can just occur when callback code
|
||||
* performs direct JDBC access via {@code Session.connection()}.
|
||||
* @param ex the SQLException
|
||||
* @return the corresponding DataAccessException instance
|
||||
* @see #setJdbcExceptionTranslator
|
||||
*/
|
||||
protected DataAccessException convertJdbcAccessException(SQLException ex) {
|
||||
SQLExceptionTranslator translator = getJdbcExceptionTranslator();
|
||||
if (translator == null) {
|
||||
translator = getDefaultJdbcExceptionTranslator();
|
||||
}
|
||||
return translator.translate("Hibernate-related JDBC operation", null, ex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain a default SQLExceptionTranslator, lazily creating it if necessary.
|
||||
* <p>Creates a default
|
||||
* {@link org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator}
|
||||
* for the SessionFactory's underlying DataSource.
|
||||
*/
|
||||
protected synchronized SQLExceptionTranslator getDefaultJdbcExceptionTranslator() {
|
||||
if (this.defaultJdbcExceptionTranslator == null) {
|
||||
this.defaultJdbcExceptionTranslator = SessionFactoryUtils.newJdbcExceptionTranslator(getSessionFactory());
|
||||
}
|
||||
return this.defaultJdbcExceptionTranslator;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Enable the specified filters on the given Session.
|
||||
* @param session the current Hibernate Session
|
||||
* @see #setFilterNames
|
||||
* @see org.hibernate.Session#enableFilter(String)
|
||||
*/
|
||||
protected void enableFilters(Session session) {
|
||||
String[] filterNames = getFilterNames();
|
||||
if (filterNames != null) {
|
||||
for (String filterName : filterNames) {
|
||||
session.enableFilter(filterName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable the specified filters on the given Session.
|
||||
* @param session the current Hibernate Session
|
||||
* @see #setFilterNames
|
||||
* @see org.hibernate.Session#disableFilter(String)
|
||||
*/
|
||||
protected void disableFilters(Session session) {
|
||||
String[] filterNames = getFilterNames();
|
||||
if (filterNames != null) {
|
||||
for (String filterName : filterNames) {
|
||||
session.disableFilter(filterName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate3;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.Session;
|
||||
|
||||
/**
|
||||
* Callback interface for Hibernate code. To be used with {@link HibernateTemplate}'s
|
||||
* execution methods, often as anonymous classes within a method implementation.
|
||||
* A typical implementation will call {@code Session.load/find/update} to perform
|
||||
* some operations on persistent objects. It can also perform direct JDBC operations
|
||||
* via Hibernate's {@code Session.connection()}, operating on a JDBC Connection.
|
||||
*
|
||||
* <p>Note that Hibernate works on unmodified plain Java objects, performing dirty
|
||||
* detection via copies made at load time. Returned objects can thus be used outside
|
||||
* of an active Hibernate Session without any hassle, e.g. for display in a web GUI.
|
||||
* Reassociating such instances with a new Session, e.g. for updates when coming
|
||||
* back from the GUI, is straightforward, as the instance has kept its identity.
|
||||
* You should care to reassociate them as early as possible though, to avoid having
|
||||
* already loaded a version from the database in the same Session.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @see HibernateTemplate
|
||||
* @see HibernateTransactionManager
|
||||
* @deprecated as of Spring 4.3, in favor of Hibernate 4.x/5.x
|
||||
*/
|
||||
@Deprecated
|
||||
public interface HibernateCallback<T> {
|
||||
|
||||
/**
|
||||
* Gets called by {@code HibernateTemplate.execute} with an active
|
||||
* Hibernate {@code Session}. Does not need to care about activating
|
||||
* or closing the {@code Session}, or handling transactions.
|
||||
* <p>If called without a thread-bound Hibernate transaction (initiated
|
||||
* by HibernateTransactionManager), the code will simply get executed on the
|
||||
* underlying JDBC connection with its transactional semantics. If Hibernate
|
||||
* is configured to use a JTA-aware DataSource, the JDBC connection and thus
|
||||
* the callback code will be transactional if a JTA transaction is active.
|
||||
* <p>Allows for returning a result object created within the callback,
|
||||
* i.e. a domain object or a collection of domain objects.
|
||||
* A thrown custom RuntimeException is treated as an application exception:
|
||||
* It gets propagated to the caller of the template.
|
||||
* @param session active Hibernate session
|
||||
* @return a result object, or {@code null} if none
|
||||
* @throws HibernateException if thrown by the Hibernate API
|
||||
* @throws SQLException if thrown by Hibernate-exposed JDBC API
|
||||
* @see HibernateTemplate#execute
|
||||
* @see HibernateTemplate#executeFind
|
||||
*/
|
||||
T doInHibernate(Session session) throws HibernateException, SQLException;
|
||||
|
||||
}
|
||||
|
|
@ -1,95 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate3;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.JDBCException;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
||||
import org.springframework.jdbc.support.SQLExceptionTranslator;
|
||||
|
||||
/**
|
||||
* {@link PersistenceExceptionTranslator} capable of translating {@link HibernateException}
|
||||
* instances to Spring's {@link DataAccessException} hierarchy.
|
||||
*
|
||||
* <p>Extended by {@link LocalSessionFactoryBean}, so there is no need to declare this
|
||||
* translator in addition to a {@code LocalSessionFactoryBean}.
|
||||
*
|
||||
* <p>When configuring the container with {@code @Configuration} classes, a {@code @Bean}
|
||||
* of this type must be registered manually.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Chris Beams
|
||||
* @since 3.1
|
||||
* @see org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor
|
||||
* @see SessionFactoryUtils#convertHibernateAccessException(HibernateException)
|
||||
* @see SQLExceptionTranslator
|
||||
* @deprecated as of Spring 4.3, in favor of Hibernate 4.x/5.x
|
||||
*/
|
||||
@Deprecated
|
||||
public class HibernateExceptionTranslator implements PersistenceExceptionTranslator {
|
||||
|
||||
private SQLExceptionTranslator jdbcExceptionTranslator;
|
||||
|
||||
|
||||
/**
|
||||
* Set the JDBC exception translator for the SessionFactory,
|
||||
* exposed via the PersistenceExceptionTranslator interface.
|
||||
* <p>Applied to any SQLException root cause of a Hibernate JDBCException,
|
||||
* overriding Hibernate's default SQLException translation (which is
|
||||
* based on Hibernate's Dialect for a specific target database).
|
||||
* @param jdbcExceptionTranslator the exception translator
|
||||
* @see java.sql.SQLException
|
||||
* @see org.hibernate.JDBCException
|
||||
* @see org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator
|
||||
* @see org.springframework.jdbc.support.SQLStateSQLExceptionTranslator
|
||||
* @see org.springframework.dao.support.PersistenceExceptionTranslator
|
||||
*/
|
||||
public void setJdbcExceptionTranslator(SQLExceptionTranslator jdbcExceptionTranslator) {
|
||||
this.jdbcExceptionTranslator = jdbcExceptionTranslator;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
|
||||
if (ex instanceof HibernateException) {
|
||||
return convertHibernateAccessException((HibernateException) ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given HibernateException to an appropriate exception from the
|
||||
* {@code org.springframework.dao} hierarchy.
|
||||
* <p>Will automatically apply a specified SQLExceptionTranslator to a
|
||||
* Hibernate JDBCException, else rely on Hibernate's default translation.
|
||||
* @param ex HibernateException that occured
|
||||
* @return a corresponding DataAccessException
|
||||
* @see SessionFactoryUtils#convertHibernateAccessException
|
||||
* @see #setJdbcExceptionTranslator
|
||||
*/
|
||||
protected DataAccessException convertHibernateAccessException(HibernateException ex) {
|
||||
if (this.jdbcExceptionTranslator != null && ex instanceof JDBCException) {
|
||||
JDBCException jdbcEx = (JDBCException) ex;
|
||||
return this.jdbcExceptionTranslator.translate(
|
||||
"Hibernate operation: " + jdbcEx.getMessage(), jdbcEx.getSQL(), jdbcEx.getSQLException());
|
||||
}
|
||||
return SessionFactoryUtils.convertHibernateAccessException(ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,157 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate3;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.hibernate.FlushMode;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.Session;
|
||||
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
|
||||
/**
|
||||
* This interceptor binds a new Hibernate Session to the thread before a method
|
||||
* call, closing and removing it afterwards in case of any method outcome.
|
||||
* If there already is a pre-bound Session (e.g. from HibernateTransactionManager,
|
||||
* or from a surrounding Hibernate-intercepted method), the interceptor simply
|
||||
* participates in it.
|
||||
*
|
||||
* <p>Application code must retrieve a Hibernate Session via the
|
||||
* {@code SessionFactoryUtils.getSession} method or - preferably -
|
||||
* Hibernate's own {@code SessionFactory.getCurrentSession()} method, to be
|
||||
* able to detect a thread-bound Session. Typically, the code will look like as follows:
|
||||
*
|
||||
* <pre class="code">
|
||||
* public void doSomeDataAccessAction() {
|
||||
* Session session = this.sessionFactory.getCurrentSession();
|
||||
* ...
|
||||
* // No need to close the Session or translate exceptions!
|
||||
* }</pre>
|
||||
*
|
||||
* Note that this interceptor automatically translates HibernateExceptions,
|
||||
* via delegating to the {@code SessionFactoryUtils.convertHibernateAccessException}
|
||||
* method that converts them to exceptions that are compatible with the
|
||||
* {@code org.springframework.dao} exception hierarchy (like HibernateTemplate does).
|
||||
* This can be turned off if the raw exceptions are preferred.
|
||||
*
|
||||
* <p>This class can be considered a declarative alternative to HibernateTemplate's
|
||||
* callback approach. The advantages are:
|
||||
* <ul>
|
||||
* <li>no anonymous classes necessary for callback implementations;
|
||||
* <li>the possibility to throw any application exceptions from within data access code.
|
||||
* </ul>
|
||||
*
|
||||
* <p>The drawback is the dependency on interceptor configuration. However, note
|
||||
* that this interceptor is usually <i>not</i> necessary in scenarios where the
|
||||
* data access code always executes within transactions. A transaction will always
|
||||
* have a thread-bound Session in the first place, so adding this interceptor to the
|
||||
* configuration just adds value when fine-tuning Session settings like the flush mode
|
||||
* - or when relying on exception translation.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @see org.hibernate.SessionFactory#getCurrentSession()
|
||||
* @see HibernateTransactionManager
|
||||
* @see HibernateTemplate
|
||||
* @deprecated as of Spring 3.2.7, in favor of either HibernateTemplate usage or
|
||||
* native Hibernate API usage within transactions, in combination with a general
|
||||
* {@link org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor}.
|
||||
* Note: This class does not have an equivalent replacement in {@code orm.hibernate4}.
|
||||
* If you desperately need a scoped Session bound through AOP, consider the newly
|
||||
* introduced {@link org.springframework.orm.hibernate3.support.OpenSessionInterceptor}.
|
||||
*/
|
||||
@Deprecated
|
||||
public class HibernateInterceptor extends HibernateAccessor implements MethodInterceptor {
|
||||
|
||||
private boolean exceptionConversionEnabled = true;
|
||||
|
||||
|
||||
/**
|
||||
* Set whether to convert any HibernateException raised to a Spring DataAccessException,
|
||||
* compatible with the {@code org.springframework.dao} exception hierarchy.
|
||||
* <p>Default is "true". Turn this flag off to let the caller receive raw exceptions
|
||||
* as-is, without any wrapping.
|
||||
* @see org.springframework.dao.DataAccessException
|
||||
*/
|
||||
public void setExceptionConversionEnabled(boolean exceptionConversionEnabled) {
|
||||
this.exceptionConversionEnabled = exceptionConversionEnabled;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
|
||||
Session session = getSession();
|
||||
SessionHolder sessionHolder =
|
||||
(SessionHolder) TransactionSynchronizationManager.getResource(getSessionFactory());
|
||||
|
||||
boolean existingTransaction = (sessionHolder != null && sessionHolder.containsSession(session));
|
||||
if (existingTransaction) {
|
||||
logger.debug("Found thread-bound Session for HibernateInterceptor");
|
||||
}
|
||||
else {
|
||||
if (sessionHolder != null) {
|
||||
sessionHolder.addSession(session);
|
||||
}
|
||||
else {
|
||||
TransactionSynchronizationManager.bindResource(getSessionFactory(), new SessionHolder(session));
|
||||
}
|
||||
}
|
||||
|
||||
FlushMode previousFlushMode = null;
|
||||
try {
|
||||
previousFlushMode = applyFlushMode(session, existingTransaction);
|
||||
enableFilters(session);
|
||||
Object retVal = methodInvocation.proceed();
|
||||
flushIfNecessary(session, existingTransaction);
|
||||
return retVal;
|
||||
}
|
||||
catch (HibernateException ex) {
|
||||
if (this.exceptionConversionEnabled) {
|
||||
throw convertHibernateAccessException(ex);
|
||||
}
|
||||
else {
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (existingTransaction) {
|
||||
logger.debug("Not closing pre-bound Hibernate Session after HibernateInterceptor");
|
||||
disableFilters(session);
|
||||
if (previousFlushMode != null) {
|
||||
session.setFlushMode(previousFlushMode);
|
||||
}
|
||||
}
|
||||
else {
|
||||
SessionFactoryUtils.closeSessionOrRegisterDeferredClose(session, getSessionFactory());
|
||||
if (sessionHolder == null || sessionHolder.doesNotHoldNonDefaultSession()) {
|
||||
TransactionSynchronizationManager.unbindResource(getSessionFactory());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a Session for use by this interceptor.
|
||||
* @see SessionFactoryUtils#getSession
|
||||
*/
|
||||
protected Session getSession() {
|
||||
return SessionFactoryUtils.getSession(
|
||||
getSessionFactory(), getEntityInterceptor(), getJdbcExceptionTranslator());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate3;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.hibernate.JDBCException;
|
||||
|
||||
import org.springframework.dao.UncategorizedDataAccessException;
|
||||
|
||||
/**
|
||||
* Hibernate-specific subclass of UncategorizedDataAccessException,
|
||||
* for JDBC exceptions that Hibernate wrapped.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @see SessionFactoryUtils#convertHibernateAccessException
|
||||
* @deprecated as of Spring 4.3, in favor of Hibernate 4.x/5.x
|
||||
*/
|
||||
@Deprecated
|
||||
@SuppressWarnings("serial")
|
||||
public class HibernateJdbcException extends UncategorizedDataAccessException {
|
||||
|
||||
public HibernateJdbcException(JDBCException ex) {
|
||||
super("JDBC exception on Hibernate data access: SQLException for SQL [" + ex.getSQL() + "]; SQL state [" +
|
||||
ex.getSQLState() + "]; error code [" + ex.getErrorCode() + "]; " + ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the underlying SQLException.
|
||||
*/
|
||||
public SQLException getSQLException() {
|
||||
return ((JDBCException) getCause()).getSQLException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the SQL that led to the problem.
|
||||
*/
|
||||
public String getSql() {
|
||||
return ((JDBCException) getCause()).getSQL();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate3;
|
||||
|
||||
import org.hibernate.UnresolvableObjectException;
|
||||
import org.hibernate.WrongClassException;
|
||||
|
||||
import org.springframework.orm.ObjectRetrievalFailureException;
|
||||
|
||||
/**
|
||||
* Hibernate-specific subclass of ObjectRetrievalFailureException.
|
||||
* Converts Hibernate's UnresolvableObjectException and WrongClassException.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @see SessionFactoryUtils#convertHibernateAccessException
|
||||
* @deprecated as of Spring 4.3, in favor of Hibernate 4.x/5.x
|
||||
*/
|
||||
@Deprecated
|
||||
@SuppressWarnings("serial")
|
||||
public class HibernateObjectRetrievalFailureException extends ObjectRetrievalFailureException {
|
||||
|
||||
public HibernateObjectRetrievalFailureException(UnresolvableObjectException ex) {
|
||||
super(ex.getEntityName(), ex.getIdentifier(), ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
public HibernateObjectRetrievalFailureException(WrongClassException ex) {
|
||||
super(ex.getEntityName(), ex.getIdentifier(), ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,921 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate3;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.Filter;
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.ReplicationMode;
|
||||
import org.hibernate.criterion.DetachedCriteria;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
|
||||
/**
|
||||
* Interface that specifies a basic set of Hibernate operations,
|
||||
* implemented by {@link HibernateTemplate}. Not often used, but a useful
|
||||
* option to enhance testability, as it can easily be mocked or stubbed.
|
||||
*
|
||||
* <p>Defines {@code HibernateTemplate}'s data access methods that
|
||||
* mirror various {@link org.hibernate.Session} methods. Users are
|
||||
* strongly encouraged to read the Hibernate {@code Session} javadocs
|
||||
* for details on the semantics of those methods.
|
||||
*
|
||||
* <p>Note that operations that return an {@link java.util.Iterator} (i.e.
|
||||
* {@code iterate(..)}) are supposed to be used within Spring-driven
|
||||
* or JTA-driven transactions (with {@link HibernateTransactionManager},
|
||||
* {@link org.springframework.transaction.jta.JtaTransactionManager},
|
||||
* or EJB CMT). Else, the {@code Iterator} won't be able to read
|
||||
* results from its {@link java.sql.ResultSet} anymore, as the underlying
|
||||
* Hibernate {@code Session} will already have been closed.
|
||||
*
|
||||
* <p>Note that lazy loading will just work with an open Hibernate
|
||||
* {@code Session}, either within a transaction or within
|
||||
* {@link org.springframework.orm.hibernate3.support.OpenSessionInViewFilter}/
|
||||
* {@link org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor}.
|
||||
* Furthermore, some operations just make sense within transactions,
|
||||
* for example: {@code contains}, {@code evict}, {@code lock},
|
||||
* {@code flush}, {@code clear}.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @see HibernateTemplate
|
||||
* @see org.hibernate.Session
|
||||
* @see HibernateTransactionManager
|
||||
* @see org.springframework.transaction.jta.JtaTransactionManager
|
||||
* @see org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
|
||||
* @see org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor
|
||||
* @deprecated as of Spring 4.3, in favor of Hibernate 4.x/5.x
|
||||
*/
|
||||
@Deprecated
|
||||
public interface HibernateOperations {
|
||||
|
||||
/**
|
||||
* Execute the action specified by the given action object within a
|
||||
* {@link org.hibernate.Session}.
|
||||
* <p>Application exceptions thrown by the action object get propagated
|
||||
* to the caller (can only be unchecked). Hibernate exceptions are
|
||||
* transformed into appropriate DAO ones. Allows for returning a result
|
||||
* object, that is a domain object or a collection of domain objects.
|
||||
* <p>Note: Callback code is not supposed to handle transactions itself!
|
||||
* Use an appropriate transaction manager like
|
||||
* {@link HibernateTransactionManager}. Generally, callback code must not
|
||||
* touch any {@code Session} lifecycle methods, like close,
|
||||
* disconnect, or reconnect, to let the template do its work.
|
||||
* @param action callback object that specifies the Hibernate action
|
||||
* @return a result object returned by the action, or {@code null}
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see HibernateTransactionManager
|
||||
* @see org.hibernate.Session
|
||||
*/
|
||||
<T> T execute(HibernateCallback<T> action) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Execute the specified action assuming that the result object is a
|
||||
* {@link List}.
|
||||
* <p>This is a convenience method for executing Hibernate find calls or
|
||||
* queries within an action.
|
||||
* @param action callback object that specifies the Hibernate action
|
||||
* @return a List result returned by the action, or {@code null}
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @deprecated as of Spring 3.2.7, in favor of using a regular {@link #execute}
|
||||
* call with a generic List type declared
|
||||
*/
|
||||
@Deprecated
|
||||
List<?> executeFind(HibernateCallback<?> action) throws DataAccessException;
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Convenience methods for loading individual objects
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Return the persistent instance of the given entity class
|
||||
* with the given identifier, or {@code null} if not found.
|
||||
* <p>This method is a thin wrapper around
|
||||
* {@link org.hibernate.Session#get(Class, java.io.Serializable)} for convenience.
|
||||
* For an explanation of the exact semantics of this method, please do refer to
|
||||
* the Hibernate API documentation in the first instance.
|
||||
* @param entityClass a persistent class
|
||||
* @param id the identifier of the persistent instance
|
||||
* @return the persistent instance, or {@code null} if not found
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#get(Class, java.io.Serializable)
|
||||
*/
|
||||
<T> T get(Class<T> entityClass, Serializable id) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Return the persistent instance of the given entity class
|
||||
* with the given identifier, or {@code null} if not found.
|
||||
* <p>Obtains the specified lock mode if the instance exists.
|
||||
* <p>This method is a thin wrapper around
|
||||
* {@link org.hibernate.Session#get(Class, java.io.Serializable, LockMode)} for convenience.
|
||||
* For an explanation of the exact semantics of this method, please do refer to
|
||||
* the Hibernate API documentation in the first instance.
|
||||
* @param entityClass a persistent class
|
||||
* @param id the identifier of the persistent instance
|
||||
* @param lockMode the lock mode to obtain
|
||||
* @return the persistent instance, or {@code null} if not found
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#get(Class, java.io.Serializable, org.hibernate.LockMode)
|
||||
*/
|
||||
<T> T get(Class<T> entityClass, Serializable id, LockMode lockMode) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Return the persistent instance of the given entity class
|
||||
* with the given identifier, or {@code null} if not found.
|
||||
* <p>This method is a thin wrapper around
|
||||
* {@link org.hibernate.Session#get(String, java.io.Serializable)} for convenience.
|
||||
* For an explanation of the exact semantics of this method, please do refer to
|
||||
* the Hibernate API documentation in the first instance.
|
||||
* @param entityName the name of the persistent entity
|
||||
* @param id the identifier of the persistent instance
|
||||
* @return the persistent instance, or {@code null} if not found
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#get(Class, java.io.Serializable)
|
||||
*/
|
||||
Object get(String entityName, Serializable id) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Return the persistent instance of the given entity class
|
||||
* with the given identifier, or {@code null} if not found.
|
||||
* Obtains the specified lock mode if the instance exists.
|
||||
* <p>This method is a thin wrapper around
|
||||
* {@link org.hibernate.Session#get(String, java.io.Serializable, LockMode)} for convenience.
|
||||
* For an explanation of the exact semantics of this method, please do refer to
|
||||
* the Hibernate API documentation in the first instance.
|
||||
* @param entityName the name of the persistent entity
|
||||
* @param id the identifier of the persistent instance
|
||||
* @param lockMode the lock mode to obtain
|
||||
* @return the persistent instance, or {@code null} if not found
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#get(Class, java.io.Serializable, org.hibernate.LockMode)
|
||||
*/
|
||||
Object get(String entityName, Serializable id, LockMode lockMode) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Return the persistent instance of the given entity class
|
||||
* with the given identifier, throwing an exception if not found.
|
||||
* <p>This method is a thin wrapper around
|
||||
* {@link org.hibernate.Session#load(Class, java.io.Serializable)} for convenience.
|
||||
* For an explanation of the exact semantics of this method, please do refer to
|
||||
* the Hibernate API documentation in the first instance.
|
||||
* @param entityClass a persistent class
|
||||
* @param id the identifier of the persistent instance
|
||||
* @return the persistent instance
|
||||
* @throws org.springframework.orm.ObjectRetrievalFailureException if not found
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#load(Class, java.io.Serializable)
|
||||
*/
|
||||
<T> T load(Class<T> entityClass, Serializable id) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Return the persistent instance of the given entity class
|
||||
* with the given identifier, throwing an exception if not found.
|
||||
* Obtains the specified lock mode if the instance exists.
|
||||
* <p>This method is a thin wrapper around
|
||||
* {@link org.hibernate.Session#load(Class, java.io.Serializable, LockMode)} for convenience.
|
||||
* For an explanation of the exact semantics of this method, please do refer to
|
||||
* the Hibernate API documentation in the first instance.
|
||||
* @param entityClass a persistent class
|
||||
* @param id the identifier of the persistent instance
|
||||
* @param lockMode the lock mode to obtain
|
||||
* @return the persistent instance
|
||||
* @throws org.springframework.orm.ObjectRetrievalFailureException if not found
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#load(Class, java.io.Serializable)
|
||||
*/
|
||||
<T> T load(Class<T> entityClass, Serializable id, LockMode lockMode) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Return the persistent instance of the given entity class
|
||||
* with the given identifier, throwing an exception if not found.
|
||||
* <p>This method is a thin wrapper around
|
||||
* {@link org.hibernate.Session#load(String, java.io.Serializable)} for convenience.
|
||||
* For an explanation of the exact semantics of this method, please do refer to
|
||||
* the Hibernate API documentation in the first instance.
|
||||
* @param entityName the name of the persistent entity
|
||||
* @param id the identifier of the persistent instance
|
||||
* @return the persistent instance
|
||||
* @throws org.springframework.orm.ObjectRetrievalFailureException if not found
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#load(Class, java.io.Serializable)
|
||||
*/
|
||||
Object load(String entityName, Serializable id) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Return the persistent instance of the given entity class
|
||||
* with the given identifier, throwing an exception if not found.
|
||||
* <p>Obtains the specified lock mode if the instance exists.
|
||||
* <p>This method is a thin wrapper around
|
||||
* {@link org.hibernate.Session#load(String, java.io.Serializable, LockMode)} for convenience.
|
||||
* For an explanation of the exact semantics of this method, please do refer to
|
||||
* the Hibernate API documentation in the first instance.
|
||||
* @param entityName the name of the persistent entity
|
||||
* @param id the identifier of the persistent instance
|
||||
* @param lockMode the lock mode to obtain
|
||||
* @return the persistent instance
|
||||
* @throws org.springframework.orm.ObjectRetrievalFailureException if not found
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#load(Class, java.io.Serializable)
|
||||
*/
|
||||
Object load(String entityName, Serializable id, LockMode lockMode) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Return all persistent instances of the given entity class.
|
||||
* Note: Use queries or criteria for retrieving a specific subset.
|
||||
* @param entityClass a persistent class
|
||||
* @return a {@link List} containing 0 or more persistent instances
|
||||
* @throws org.springframework.dao.DataAccessException if there is a Hibernate error
|
||||
* @see org.hibernate.Session#createCriteria
|
||||
*/
|
||||
<T> List<T> loadAll(Class<T> entityClass) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Load the persistent instance with the given identifier
|
||||
* into the given object, throwing an exception if not found.
|
||||
* <p>This method is a thin wrapper around
|
||||
* {@link org.hibernate.Session#load(Object, java.io.Serializable)} for convenience.
|
||||
* For an explanation of the exact semantics of this method, please do refer to
|
||||
* the Hibernate API documentation in the first instance.
|
||||
* @param entity the object (of the target class) to load into
|
||||
* @param id the identifier of the persistent instance
|
||||
* @throws org.springframework.orm.ObjectRetrievalFailureException if not found
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#load(Object, java.io.Serializable)
|
||||
*/
|
||||
void load(Object entity, Serializable id) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Re-read the state of the given persistent instance.
|
||||
* @param entity the persistent instance to re-read
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#refresh(Object)
|
||||
*/
|
||||
void refresh(Object entity) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Re-read the state of the given persistent instance.
|
||||
* Obtains the specified lock mode for the instance.
|
||||
* @param entity the persistent instance to re-read
|
||||
* @param lockMode the lock mode to obtain
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#refresh(Object, org.hibernate.LockMode)
|
||||
*/
|
||||
void refresh(Object entity, LockMode lockMode) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Check whether the given object is in the Session cache.
|
||||
* @param entity the persistence instance to check
|
||||
* @return whether the given object is in the Session cache
|
||||
* @throws org.springframework.dao.DataAccessException if there is a Hibernate error
|
||||
* @see org.hibernate.Session#contains
|
||||
*/
|
||||
boolean contains(Object entity) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Remove the given object from the {@link org.hibernate.Session} cache.
|
||||
* @param entity the persistent instance to evict
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#evict
|
||||
*/
|
||||
void evict(Object entity) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Force initialization of a Hibernate proxy or persistent collection.
|
||||
* @param proxy a proxy for a persistent object or a persistent collection
|
||||
* @throws DataAccessException if we can't initialize the proxy, for example
|
||||
* because it is not associated with an active Session
|
||||
* @see org.hibernate.Hibernate#initialize
|
||||
*/
|
||||
void initialize(Object proxy) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Return an enabled Hibernate {@link Filter} for the given filter name.
|
||||
* The returned {@code Filter} instance can be used to set filter parameters.
|
||||
* @param filterName the name of the filter
|
||||
* @return the enabled Hibernate {@code Filter} (either already
|
||||
* enabled or enabled on the fly by this operation)
|
||||
* @throws IllegalStateException if we are not running within a
|
||||
* transactional Session (in which case this operation does not make sense)
|
||||
*/
|
||||
Filter enableFilter(String filterName) throws IllegalStateException;
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Convenience methods for storing individual objects
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Obtain the specified lock level upon the given object, implicitly
|
||||
* checking whether the corresponding database entry still exists.
|
||||
* @param entity the persistent instance to lock
|
||||
* @param lockMode the lock mode to obtain
|
||||
* @throws org.springframework.orm.ObjectOptimisticLockingFailureException if not found
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#lock(Object, org.hibernate.LockMode)
|
||||
*/
|
||||
void lock(Object entity, LockMode lockMode) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Obtain the specified lock level upon the given object, implicitly
|
||||
* checking whether the corresponding database entry still exists.
|
||||
* @param entityName the name of the persistent entity
|
||||
* @param entity the persistent instance to lock
|
||||
* @param lockMode the lock mode to obtain
|
||||
* @throws org.springframework.orm.ObjectOptimisticLockingFailureException if not found
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#lock(String, Object, org.hibernate.LockMode)
|
||||
*/
|
||||
void lock(String entityName, Object entity, LockMode lockMode) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Persist the given transient instance.
|
||||
* @param entity the transient instance to persist
|
||||
* @return the generated identifier
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#save(Object)
|
||||
*/
|
||||
Serializable save(Object entity) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Persist the given transient instance.
|
||||
* @param entityName the name of the persistent entity
|
||||
* @param entity the transient instance to persist
|
||||
* @return the generated identifier
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#save(String, Object)
|
||||
*/
|
||||
Serializable save(String entityName, Object entity) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Update the given persistent instance,
|
||||
* associating it with the current Hibernate {@link org.hibernate.Session}.
|
||||
* @param entity the persistent instance to update
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#update(Object)
|
||||
*/
|
||||
void update(Object entity) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Update the given persistent instance,
|
||||
* associating it with the current Hibernate {@link org.hibernate.Session}.
|
||||
* <p>Obtains the specified lock mode if the instance exists, implicitly
|
||||
* checking whether the corresponding database entry still exists.
|
||||
* @param entity the persistent instance to update
|
||||
* @param lockMode the lock mode to obtain
|
||||
* @throws org.springframework.orm.ObjectOptimisticLockingFailureException if not found
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#update(Object)
|
||||
*/
|
||||
void update(Object entity, LockMode lockMode) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Update the given persistent instance,
|
||||
* associating it with the current Hibernate {@link org.hibernate.Session}.
|
||||
* @param entityName the name of the persistent entity
|
||||
* @param entity the persistent instance to update
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#update(String, Object)
|
||||
*/
|
||||
void update(String entityName, Object entity) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Update the given persistent instance,
|
||||
* associating it with the current Hibernate {@link org.hibernate.Session}.
|
||||
* <p>Obtains the specified lock mode if the instance exists, implicitly
|
||||
* checking whether the corresponding database entry still exists.
|
||||
* @param entityName the name of the persistent entity
|
||||
* @param entity the persistent instance to update
|
||||
* @param lockMode the lock mode to obtain
|
||||
* @throws org.springframework.orm.ObjectOptimisticLockingFailureException if not found
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#update(String, Object)
|
||||
*/
|
||||
void update(String entityName, Object entity, LockMode lockMode) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Save or update the given persistent instance,
|
||||
* according to its id (matching the configured "unsaved-value"?).
|
||||
* Associates the instance with the current Hibernate {@link org.hibernate.Session}.
|
||||
* @param entity the persistent instance to save or update
|
||||
* (to be associated with the Hibernate {@code Session})
|
||||
* @throws DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#saveOrUpdate(Object)
|
||||
*/
|
||||
void saveOrUpdate(Object entity) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Save or update the given persistent instance,
|
||||
* according to its id (matching the configured "unsaved-value"?).
|
||||
* Associates the instance with the current Hibernate {@code Session}.
|
||||
* @param entityName the name of the persistent entity
|
||||
* @param entity the persistent instance to save or update
|
||||
* (to be associated with the Hibernate {@code Session})
|
||||
* @throws DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#saveOrUpdate(String, Object)
|
||||
*/
|
||||
void saveOrUpdate(String entityName, Object entity) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Persist the state of the given detached instance according to the
|
||||
* given replication mode, reusing the current identifier value.
|
||||
* @param entity the persistent object to replicate
|
||||
* @param replicationMode the Hibernate ReplicationMode
|
||||
* @throws DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#replicate(Object, org.hibernate.ReplicationMode)
|
||||
*/
|
||||
void replicate(Object entity, ReplicationMode replicationMode) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Persist the state of the given detached instance according to the
|
||||
* given replication mode, reusing the current identifier value.
|
||||
* @param entityName the name of the persistent entity
|
||||
* @param entity the persistent object to replicate
|
||||
* @param replicationMode the Hibernate ReplicationMode
|
||||
* @throws DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#replicate(String, Object, org.hibernate.ReplicationMode)
|
||||
*/
|
||||
void replicate(String entityName, Object entity, ReplicationMode replicationMode) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Persist the given transient instance. Follows JSR-220 semantics.
|
||||
* <p>Similar to {@code save}, associating the given object
|
||||
* with the current Hibernate {@link org.hibernate.Session}.
|
||||
* @param entity the persistent instance to persist
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#persist(Object)
|
||||
* @see #save
|
||||
*/
|
||||
void persist(Object entity) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Persist the given transient instance. Follows JSR-220 semantics.
|
||||
* <p>Similar to {@code save}, associating the given object
|
||||
* with the current Hibernate {@link org.hibernate.Session}.
|
||||
* @param entityName the name of the persistent entity
|
||||
* @param entity the persistent instance to persist
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#persist(String, Object)
|
||||
* @see #save
|
||||
*/
|
||||
void persist(String entityName, Object entity) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Copy the state of the given object onto the persistent object
|
||||
* with the same identifier. Follows JSR-220 semantics.
|
||||
* <p>Similar to {@code saveOrUpdate}, but never associates the given
|
||||
* object with the current Hibernate Session. In case of a new entity,
|
||||
* the state will be copied over as well.
|
||||
* <p>Note that {@code merge} will <i>not</i> update the identifiers
|
||||
* in the passed-in object graph (in contrast to TopLink)! Consider
|
||||
* registering Spring's {@code IdTransferringMergeEventListener} if
|
||||
* you would like to have newly assigned ids transferred to the original
|
||||
* object graph too.
|
||||
* @param entity the object to merge with the corresponding persistence instance
|
||||
* @return the updated, registered persistent instance
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#merge(Object)
|
||||
* @see #saveOrUpdate
|
||||
* @see org.springframework.orm.hibernate3.support.IdTransferringMergeEventListener
|
||||
*/
|
||||
<T> T merge(T entity) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Copy the state of the given object onto the persistent object
|
||||
* with the same identifier. Follows JSR-220 semantics.
|
||||
* <p>Similar to {@code saveOrUpdate}, but never associates the given
|
||||
* object with the current Hibernate {@link org.hibernate.Session}. In
|
||||
* the case of a new entity, the state will be copied over as well.
|
||||
* <p>Note that {@code merge} will <i>not</i> update the identifiers
|
||||
* in the passed-in object graph (in contrast to TopLink)! Consider
|
||||
* registering Spring's {@code IdTransferringMergeEventListener}
|
||||
* if you would like to have newly assigned ids transferred to the
|
||||
* original object graph too.
|
||||
* @param entityName the name of the persistent entity
|
||||
* @param entity the object to merge with the corresponding persistence instance
|
||||
* @return the updated, registered persistent instance
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#merge(String, Object)
|
||||
* @see #saveOrUpdate
|
||||
*/
|
||||
<T> T merge(String entityName, T entity) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Delete the given persistent instance.
|
||||
* @param entity the persistent instance to delete
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#delete(Object)
|
||||
*/
|
||||
void delete(Object entity) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Delete the given persistent instance.
|
||||
* <p>Obtains the specified lock mode if the instance exists, implicitly
|
||||
* checking whether the corresponding database entry still exists.
|
||||
* @param entity the persistent instance to delete
|
||||
* @param lockMode the lock mode to obtain
|
||||
* @throws org.springframework.orm.ObjectOptimisticLockingFailureException if not found
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#delete(Object)
|
||||
*/
|
||||
void delete(Object entity, LockMode lockMode) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Delete the given persistent instance.
|
||||
* @param entityName the name of the persistent entity
|
||||
* @param entity the persistent instance to delete
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#delete(Object)
|
||||
*/
|
||||
void delete(String entityName, Object entity) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Delete the given persistent instance.
|
||||
* <p>Obtains the specified lock mode if the instance exists, implicitly
|
||||
* checking whether the corresponding database entry still exists.
|
||||
* @param entityName the name of the persistent entity
|
||||
* @param entity the persistent instance to delete
|
||||
* @param lockMode the lock mode to obtain
|
||||
* @throws org.springframework.orm.ObjectOptimisticLockingFailureException if not found
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#delete(Object)
|
||||
*/
|
||||
void delete(String entityName, Object entity, LockMode lockMode) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Delete all given persistent instances.
|
||||
* <p>This can be combined with any of the find methods to delete by query
|
||||
* in two lines of code.
|
||||
* @param entities the persistent instances to delete
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#delete(Object)
|
||||
*/
|
||||
void deleteAll(Collection<?> entities) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Flush all pending saves, updates and deletes to the database.
|
||||
* <p>Only invoke this for selective eager flushing, for example when
|
||||
* JDBC code needs to see certain changes within the same transaction.
|
||||
* Else, it is preferable to rely on auto-flushing at transaction
|
||||
* completion.
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#flush
|
||||
*/
|
||||
void flush() throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Remove all objects from the {@link org.hibernate.Session} cache, and
|
||||
* cancel all pending saves, updates and deletes.
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#clear
|
||||
*/
|
||||
void clear() throws DataAccessException;
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Convenience finder methods for HQL strings
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Execute an HQL query.
|
||||
* @param queryString a query expressed in Hibernate's query language
|
||||
* @return a {@link List} containing the results of the query execution
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#createQuery
|
||||
*/
|
||||
List<?> find(String queryString) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Execute an HQL query, binding one value to a "?" parameter in the
|
||||
* query string.
|
||||
* @param queryString a query expressed in Hibernate's query language
|
||||
* @param value the value of the parameter
|
||||
* @return a {@link List} containing the results of the query execution
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#createQuery
|
||||
*/
|
||||
List<?> find(String queryString, Object value) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Execute an HQL query, binding a number of values to "?" parameters
|
||||
* in the query string.
|
||||
* @param queryString a query expressed in Hibernate's query language
|
||||
* @param values the values of the parameters
|
||||
* @return a {@link List} containing the results of the query execution
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#createQuery
|
||||
*/
|
||||
List<?> find(String queryString, Object... values) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Execute an HQL query, binding one value to a ":" named parameter
|
||||
* in the query string.
|
||||
* @param queryString a query expressed in Hibernate's query language
|
||||
* @param paramName the name of the parameter
|
||||
* @param value the value of the parameter
|
||||
* @return a {@link List} containing the results of the query execution
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#getNamedQuery(String)
|
||||
*/
|
||||
List<?> findByNamedParam(String queryString, String paramName, Object value) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Execute an HQL query, binding a number of values to ":" named
|
||||
* parameters in the query string.
|
||||
* @param queryString a query expressed in Hibernate's query language
|
||||
* @param paramNames the names of the parameters
|
||||
* @param values the values of the parameters
|
||||
* @return a {@link List} containing the results of the query execution
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#getNamedQuery(String)
|
||||
*/
|
||||
List<?> findByNamedParam(String queryString, String[] paramNames, Object[] values) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Execute an HQL query, binding the properties of the given bean to
|
||||
* <i>named</i> parameters in the query string.
|
||||
* @param queryString a query expressed in Hibernate's query language
|
||||
* @param valueBean the values of the parameters
|
||||
* @return a {@link List} containing the results of the query execution
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Query#setProperties
|
||||
* @see org.hibernate.Session#createQuery
|
||||
*/
|
||||
List<?> findByValueBean(String queryString, Object valueBean) throws DataAccessException;
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Convenience finder methods for named queries
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Execute a named query.
|
||||
* <p>A named query is defined in a Hibernate mapping file.
|
||||
* @param queryName the name of a Hibernate query in a mapping file
|
||||
* @return a {@link List} containing the results of the query execution
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#getNamedQuery(String)
|
||||
*/
|
||||
List<?> findByNamedQuery(String queryName) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Execute a named query, binding one value to a "?" parameter in
|
||||
* the query string.
|
||||
* <p>A named query is defined in a Hibernate mapping file.
|
||||
* @param queryName the name of a Hibernate query in a mapping file
|
||||
* @param value the value of the parameter
|
||||
* @return a {@link List} containing the results of the query execution
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#getNamedQuery(String)
|
||||
*/
|
||||
List<?> findByNamedQuery(String queryName, Object value) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Execute a named query binding a number of values to "?" parameters
|
||||
* in the query string.
|
||||
* <p>A named query is defined in a Hibernate mapping file.
|
||||
* @param queryName the name of a Hibernate query in a mapping file
|
||||
* @param values the values of the parameters
|
||||
* @return a {@link List} containing the results of the query execution
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#getNamedQuery(String)
|
||||
*/
|
||||
List<?> findByNamedQuery(String queryName, Object... values) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Execute a named query, binding one value to a ":" named parameter
|
||||
* in the query string.
|
||||
* <p>A named query is defined in a Hibernate mapping file.
|
||||
* @param queryName the name of a Hibernate query in a mapping file
|
||||
* @param paramName the name of parameter
|
||||
* @param value the value of the parameter
|
||||
* @return a {@link List} containing the results of the query execution
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#getNamedQuery(String)
|
||||
*/
|
||||
List<?> findByNamedQueryAndNamedParam(String queryName, String paramName, Object value)
|
||||
throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Execute a named query, binding a number of values to ":" named
|
||||
* parameters in the query string.
|
||||
* <p>A named query is defined in a Hibernate mapping file.
|
||||
* @param queryName the name of a Hibernate query in a mapping file
|
||||
* @param paramNames the names of the parameters
|
||||
* @param values the values of the parameters
|
||||
* @return a {@link List} containing the results of the query execution
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#getNamedQuery(String)
|
||||
*/
|
||||
List<?> findByNamedQueryAndNamedParam(String queryName, String[] paramNames, Object[] values)
|
||||
throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Execute a named query, binding the properties of the given bean to
|
||||
* ":" named parameters in the query string.
|
||||
* <p>A named query is defined in a Hibernate mapping file.
|
||||
* @param queryName the name of a Hibernate query in a mapping file
|
||||
* @param valueBean the values of the parameters
|
||||
* @return a {@link List} containing the results of the query execution
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Query#setProperties
|
||||
* @see org.hibernate.Session#getNamedQuery(String)
|
||||
*/
|
||||
List<?> findByNamedQueryAndValueBean(String queryName, Object valueBean) throws DataAccessException;
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Convenience finder methods for detached criteria
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Execute a query based on a given Hibernate criteria object.
|
||||
* @param criteria the detached Hibernate criteria object.
|
||||
* <b>Note: Do not reuse criteria objects! They need to recreated per execution,
|
||||
* due to the suboptimal design of Hibernate's criteria facility.</b>
|
||||
* @return a {@link List} containing 0 or more persistent instances
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.criterion.DetachedCriteria#getExecutableCriteria(org.hibernate.Session)
|
||||
*/
|
||||
List<?> findByCriteria(DetachedCriteria criteria) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Execute a query based on the given Hibernate criteria object.
|
||||
* @param criteria the detached Hibernate criteria object.
|
||||
* <b>Note: Do not reuse criteria objects! They need to recreated per execution,
|
||||
* due to the suboptimal design of Hibernate's criteria facility.</b>
|
||||
* @param firstResult the index of the first result object to be retrieved
|
||||
* (numbered from 0)
|
||||
* @param maxResults the maximum number of result objects to retrieve
|
||||
* (or <=0 for no limit)
|
||||
* @return a {@link List} containing 0 or more persistent instances
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.criterion.DetachedCriteria#getExecutableCriteria(org.hibernate.Session)
|
||||
* @see org.hibernate.Criteria#setFirstResult(int)
|
||||
* @see org.hibernate.Criteria#setMaxResults(int)
|
||||
*/
|
||||
List<?> findByCriteria(DetachedCriteria criteria, int firstResult, int maxResults) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Execute a query based on the given example entity object.
|
||||
* @param exampleEntity an instance of the desired entity,
|
||||
* serving as example for "query-by-example"
|
||||
* @return a {@link List} containing 0 or more persistent instances
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.criterion.Example#create(Object)
|
||||
*/
|
||||
<T> List<T> findByExample(T exampleEntity) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Execute a query based on the given example entity object.
|
||||
* @param entityName the name of the persistent entity
|
||||
* @param exampleEntity an instance of the desired entity,
|
||||
* serving as example for "query-by-example"
|
||||
* @return a {@link List} containing 0 or more persistent instances
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.criterion.Example#create(Object)
|
||||
*/
|
||||
<T> List<T> findByExample(String entityName, T exampleEntity) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Execute a query based on a given example entity object.
|
||||
* @param exampleEntity an instance of the desired entity,
|
||||
* serving as example for "query-by-example"
|
||||
* @param firstResult the index of the first result object to be retrieved
|
||||
* (numbered from 0)
|
||||
* @param maxResults the maximum number of result objects to retrieve
|
||||
* (or <=0 for no limit)
|
||||
* @return a {@link List} containing 0 or more persistent instances
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.criterion.Example#create(Object)
|
||||
* @see org.hibernate.Criteria#setFirstResult(int)
|
||||
* @see org.hibernate.Criteria#setMaxResults(int)
|
||||
*/
|
||||
<T> List<T> findByExample(T exampleEntity, int firstResult, int maxResults) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Execute a query based on a given example entity object.
|
||||
* @param entityName the name of the persistent entity
|
||||
* @param exampleEntity an instance of the desired entity,
|
||||
* serving as example for "query-by-example"
|
||||
* @param firstResult the index of the first result object to be retrieved
|
||||
* (numbered from 0)
|
||||
* @param maxResults the maximum number of result objects to retrieve
|
||||
* (or <=0 for no limit)
|
||||
* @return a {@link List} containing 0 or more persistent instances
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.criterion.Example#create(Object)
|
||||
* @see org.hibernate.Criteria#setFirstResult(int)
|
||||
* @see org.hibernate.Criteria#setMaxResults(int)
|
||||
*/
|
||||
<T> List<T> findByExample(String entityName, T exampleEntity, int firstResult, int maxResults)
|
||||
throws DataAccessException;
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Convenience query methods for iteration and bulk updates/deletes
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Execute a query for persistent instances.
|
||||
* <p>Returns the results as an {@link Iterator}. Entities returned are
|
||||
* initialized on demand. See the Hibernate API documentation for details.
|
||||
* @param queryString a query expressed in Hibernate's query language
|
||||
* @return an {@link Iterator} containing 0 or more persistent instances
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#createQuery
|
||||
* @see org.hibernate.Query#iterate
|
||||
*/
|
||||
Iterator<?> iterate(String queryString) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Execute a query for persistent instances, binding one value
|
||||
* to a "?" parameter in the query string.
|
||||
* <p>Returns the results as an {@link Iterator}. Entities returned are
|
||||
* initialized on demand. See the Hibernate API documentation for details.
|
||||
* @param queryString a query expressed in Hibernate's query language
|
||||
* @param value the value of the parameter
|
||||
* @return an {@link Iterator} containing 0 or more persistent instances
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#createQuery
|
||||
* @see org.hibernate.Query#iterate
|
||||
*/
|
||||
Iterator<?> iterate(String queryString, Object value) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Execute a query for persistent instances, binding a number of
|
||||
* values to "?" parameters in the query string.
|
||||
* <p>Returns the results as an {@link Iterator}. Entities returned are
|
||||
* initialized on demand. See the Hibernate API documentation for details.
|
||||
* @param queryString a query expressed in Hibernate's query language
|
||||
* @param values the values of the parameters
|
||||
* @return an {@link Iterator} containing 0 or more persistent instances
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#createQuery
|
||||
* @see org.hibernate.Query#iterate
|
||||
*/
|
||||
Iterator<?> iterate(String queryString, Object... values) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Immediately close an {@link Iterator} created by any of the various
|
||||
* {@code iterate(..)} operations, instead of waiting until the
|
||||
* session is closed or disconnected.
|
||||
* @param it the {@code Iterator} to close
|
||||
* @throws DataAccessException if the {@code Iterator} could not be closed
|
||||
* @see org.hibernate.Hibernate#close
|
||||
*/
|
||||
void closeIterator(Iterator<?> it) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Update/delete all objects according to the given query.
|
||||
* @param queryString an update/delete query expressed in Hibernate's query language
|
||||
* @return the number of instances updated/deleted
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#createQuery
|
||||
* @see org.hibernate.Query#executeUpdate
|
||||
*/
|
||||
int bulkUpdate(String queryString) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Update/delete all objects according to the given query, binding one value
|
||||
* to a "?" parameter in the query string.
|
||||
* @param queryString an update/delete query expressed in Hibernate's query language
|
||||
* @param value the value of the parameter
|
||||
* @return the number of instances updated/deleted
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#createQuery
|
||||
* @see org.hibernate.Query#executeUpdate
|
||||
*/
|
||||
int bulkUpdate(String queryString, Object value) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Update/delete all objects according to the given query, binding a number of
|
||||
* values to "?" parameters in the query string.
|
||||
* @param queryString an update/delete query expressed in Hibernate's query language
|
||||
* @param values the values of the parameters
|
||||
* @return the number of instances updated/deleted
|
||||
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
|
||||
* @see org.hibernate.Session#createQuery
|
||||
* @see org.hibernate.Query#executeUpdate
|
||||
*/
|
||||
int bulkUpdate(String queryString, Object... values) throws DataAccessException;
|
||||
|
||||
}
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate3;
|
||||
|
||||
import org.hibernate.OptimisticLockException;
|
||||
import org.hibernate.StaleObjectStateException;
|
||||
import org.hibernate.StaleStateException;
|
||||
|
||||
import org.springframework.orm.ObjectOptimisticLockingFailureException;
|
||||
|
||||
/**
|
||||
* Hibernate-specific subclass of ObjectOptimisticLockingFailureException.
|
||||
* Converts Hibernate's StaleObjectStateException, StaleStateException
|
||||
* and OptimisticLockException.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @see SessionFactoryUtils#convertHibernateAccessException
|
||||
* @deprecated as of Spring 4.3, in favor of Hibernate 4.x/5.x
|
||||
*/
|
||||
@Deprecated
|
||||
@SuppressWarnings("serial")
|
||||
public class HibernateOptimisticLockingFailureException extends ObjectOptimisticLockingFailureException {
|
||||
|
||||
public HibernateOptimisticLockingFailureException(StaleObjectStateException ex) {
|
||||
super(ex.getEntityName(), ex.getIdentifier(), ex);
|
||||
}
|
||||
|
||||
public HibernateOptimisticLockingFailureException(StaleStateException ex) {
|
||||
super(ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
public HibernateOptimisticLockingFailureException(OptimisticLockException ex) {
|
||||
super(ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate3;
|
||||
|
||||
import org.hibernate.QueryException;
|
||||
|
||||
import org.springframework.dao.InvalidDataAccessResourceUsageException;
|
||||
|
||||
/**
|
||||
* Hibernate-specific subclass of InvalidDataAccessResourceUsageException,
|
||||
* thrown on invalid HQL query syntax.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @see SessionFactoryUtils#convertHibernateAccessException
|
||||
* @deprecated as of Spring 4.3, in favor of Hibernate 4.x/5.x
|
||||
*/
|
||||
@Deprecated
|
||||
@SuppressWarnings("serial")
|
||||
public class HibernateQueryException extends InvalidDataAccessResourceUsageException {
|
||||
|
||||
public HibernateQueryException(QueryException ex) {
|
||||
super(ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the HQL query string that was invalid.
|
||||
*/
|
||||
public String getQueryString() {
|
||||
return ((QueryException) getCause()).getQueryString();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate3;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
|
||||
import org.springframework.dao.UncategorizedDataAccessException;
|
||||
|
||||
/**
|
||||
* Hibernate-specific subclass of UncategorizedDataAccessException,
|
||||
* for Hibernate system errors that do not match any concrete
|
||||
* {@code org.springframework.dao} exceptions.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @see SessionFactoryUtils#convertHibernateAccessException
|
||||
* @deprecated as of Spring 4.3, in favor of Hibernate 4.x/5.x
|
||||
*/
|
||||
@Deprecated
|
||||
@SuppressWarnings("serial")
|
||||
public class HibernateSystemException extends UncategorizedDataAccessException {
|
||||
|
||||
/**
|
||||
* Create a new HibernateSystemException,
|
||||
* wrapping an arbitrary HibernateException.
|
||||
* @param cause the HibernateException thrown
|
||||
*/
|
||||
public HibernateSystemException(HibernateException cause) {
|
||||
super(cause != null ? cause.getMessage() : null, cause);
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,933 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate3;
|
||||
|
||||
import java.sql.Connection;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.hibernate.ConnectionReleaseMode;
|
||||
import org.hibernate.FlushMode;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.Interceptor;
|
||||
import org.hibernate.JDBCException;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.Transaction;
|
||||
import org.hibernate.exception.GenericJDBCException;
|
||||
import org.hibernate.impl.SessionImpl;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.DataAccessResourceFailureException;
|
||||
import org.springframework.jdbc.datasource.ConnectionHolder;
|
||||
import org.springframework.jdbc.datasource.DataSourceUtils;
|
||||
import org.springframework.jdbc.datasource.JdbcTransactionObjectSupport;
|
||||
import org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy;
|
||||
import org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator;
|
||||
import org.springframework.jdbc.support.SQLExceptionTranslator;
|
||||
import org.springframework.transaction.CannotCreateTransactionException;
|
||||
import org.springframework.transaction.IllegalTransactionStateException;
|
||||
import org.springframework.transaction.InvalidIsolationLevelException;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.TransactionSystemException;
|
||||
import org.springframework.transaction.support.AbstractPlatformTransactionManager;
|
||||
import org.springframework.transaction.support.DefaultTransactionStatus;
|
||||
import org.springframework.transaction.support.ResourceTransactionManager;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.transaction.PlatformTransactionManager}
|
||||
* implementation for a single Hibernate {@link org.hibernate.SessionFactory}.
|
||||
* Binds a Hibernate Session from the specified factory to the thread, potentially
|
||||
* allowing for one thread-bound Session per factory. {@link SessionFactoryUtils}
|
||||
* and {@link HibernateTemplate} are aware of thread-bound Sessions and participate
|
||||
* in such transactions automatically. Using either of those or going through
|
||||
* {@code SessionFactory.getCurrentSession()} is required for Hibernate
|
||||
* access code that needs to support this transaction handling mechanism.
|
||||
*
|
||||
* <p>Supports custom isolation levels, and timeouts that get applied as
|
||||
* Hibernate transaction timeouts.
|
||||
*
|
||||
* <p>This transaction manager is appropriate for applications that use a single
|
||||
* Hibernate SessionFactory for transactional data access, but it also supports
|
||||
* direct DataSource access within a transaction (i.e. plain JDBC code working
|
||||
* with the same DataSource). This allows for mixing services which access Hibernate
|
||||
* and services which use plain JDBC (without being aware of Hibernate)!
|
||||
* Application code needs to stick to the same simple Connection lookup pattern as
|
||||
* with {@link org.springframework.jdbc.datasource.DataSourceTransactionManager}
|
||||
* (i.e. {@link org.springframework.jdbc.datasource.DataSourceUtils#getConnection}
|
||||
* or going through a
|
||||
* {@link org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy}).
|
||||
*
|
||||
* <p>Note: To be able to register a DataSource's Connection for plain JDBC code,
|
||||
* this instance needs to be aware of the DataSource ({@link #setDataSource}).
|
||||
* The given DataSource should obviously match the one used by the given
|
||||
* SessionFactory. To achieve this, configure both to the same JNDI DataSource,
|
||||
* or preferably create the SessionFactory with {@link LocalSessionFactoryBean} and
|
||||
* a local DataSource (which will be autodetected by this transaction manager).
|
||||
*
|
||||
* <p>JTA (usually through {@link org.springframework.transaction.jta.JtaTransactionManager})
|
||||
* is necessary for accessing multiple transactional resources within the same
|
||||
* transaction. The DataSource that Hibernate uses needs to be JTA-enabled in
|
||||
* such a scenario (see container setup). Normally, JTA setup for Hibernate is
|
||||
* somewhat container-specific due to the JTA TransactionManager lookup, required
|
||||
* for proper transactional handling of the SessionFactory-level read-write cache.
|
||||
*
|
||||
* <p>Fortunately, there is an easier way with Spring: {@link SessionFactoryUtils}
|
||||
* (and thus {@link HibernateTemplate}) registers synchronizations with Spring's
|
||||
* {@link org.springframework.transaction.support.TransactionSynchronizationManager}
|
||||
* (as used by {@link org.springframework.transaction.jta.JtaTransactionManager}),
|
||||
* for proper after-completion callbacks. Therefore, as long as Spring's
|
||||
* JtaTransactionManager drives the JTA transactions, Hibernate does not require
|
||||
* any special configuration for proper JTA participation. Note that there are
|
||||
* special restrictions with EJB CMT and restrictive JTA subsystems: See
|
||||
* {@link org.springframework.transaction.jta.JtaTransactionManager}'s javadoc for details.
|
||||
*
|
||||
* <p>This transaction manager supports nested transactions via JDBC 3.0 Savepoints.
|
||||
* The {@link #setNestedTransactionAllowed} "nestedTransactionAllowed"} flag defaults
|
||||
* to "false", though, as nested transactions will just apply to the JDBC Connection,
|
||||
* not to the Hibernate Session and its cached entity objects and related context.
|
||||
* You can manually set the flag to "true" if you want to use nested transactions
|
||||
* for JDBC access code which participates in Hibernate transactions (provided that
|
||||
* your JDBC driver supports Savepoints). <i>Note that Hibernate itself does not
|
||||
* support nested transactions! Hence, do not expect Hibernate access code to
|
||||
* semantically participate in a nested transaction.</i>
|
||||
*
|
||||
* <p>Requires Hibernate 3.6.x, as of Spring 4.0.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @see #setSessionFactory
|
||||
* @see #setDataSource
|
||||
* @see LocalSessionFactoryBean
|
||||
* @see SessionFactoryUtils#getSession
|
||||
* @see SessionFactoryUtils#applyTransactionTimeout
|
||||
* @see SessionFactoryUtils#releaseSession
|
||||
* @see HibernateTemplate
|
||||
* @see org.hibernate.SessionFactory#getCurrentSession()
|
||||
* @see org.springframework.jdbc.datasource.DataSourceUtils#getConnection
|
||||
* @see org.springframework.jdbc.datasource.DataSourceUtils#applyTransactionTimeout
|
||||
* @see org.springframework.jdbc.datasource.DataSourceUtils#releaseConnection
|
||||
* @see org.springframework.jdbc.core.JdbcTemplate
|
||||
* @see org.springframework.jdbc.datasource.DataSourceTransactionManager
|
||||
* @see org.springframework.transaction.jta.JtaTransactionManager
|
||||
* @deprecated as of Spring 4.3, in favor of Hibernate 4.x/5.x
|
||||
*/
|
||||
@Deprecated
|
||||
@SuppressWarnings("serial")
|
||||
public class HibernateTransactionManager extends AbstractPlatformTransactionManager
|
||||
implements ResourceTransactionManager, BeanFactoryAware, InitializingBean {
|
||||
|
||||
private SessionFactory sessionFactory;
|
||||
|
||||
private DataSource dataSource;
|
||||
|
||||
private boolean autodetectDataSource = true;
|
||||
|
||||
private boolean prepareConnection = true;
|
||||
|
||||
private boolean hibernateManagedSession = false;
|
||||
|
||||
private boolean earlyFlushBeforeCommit = false;
|
||||
|
||||
private Object entityInterceptor;
|
||||
|
||||
private SQLExceptionTranslator jdbcExceptionTranslator;
|
||||
|
||||
private SQLExceptionTranslator defaultJdbcExceptionTranslator;
|
||||
|
||||
/**
|
||||
* Just needed for entityInterceptorBeanName.
|
||||
* @see #setEntityInterceptorBeanName
|
||||
*/
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new HibernateTransactionManager instance.
|
||||
* A SessionFactory has to be set to be able to use it.
|
||||
* @see #setSessionFactory
|
||||
*/
|
||||
public HibernateTransactionManager() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new HibernateTransactionManager instance.
|
||||
* @param sessionFactory SessionFactory to manage transactions for
|
||||
*/
|
||||
public HibernateTransactionManager(SessionFactory sessionFactory) {
|
||||
this.sessionFactory = sessionFactory;
|
||||
afterPropertiesSet();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the SessionFactory that this instance should manage transactions for.
|
||||
*/
|
||||
public void setSessionFactory(SessionFactory sessionFactory) {
|
||||
this.sessionFactory = sessionFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the SessionFactory that this instance should manage transactions for.
|
||||
*/
|
||||
public SessionFactory getSessionFactory() {
|
||||
return this.sessionFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the JDBC DataSource that this instance should manage transactions for.
|
||||
* The DataSource should match the one used by the Hibernate SessionFactory:
|
||||
* for example, you could specify the same JNDI DataSource for both.
|
||||
* <p>If the SessionFactory was configured with LocalDataSourceConnectionProvider,
|
||||
* i.e. by Spring's LocalSessionFactoryBean with a specified "dataSource",
|
||||
* the DataSource will be auto-detected: You can still explicitly specify the
|
||||
* DataSource, but you don't need to in this case.
|
||||
* <p>A transactional JDBC Connection for this DataSource will be provided to
|
||||
* application code accessing this DataSource directly via DataSourceUtils
|
||||
* or JdbcTemplate. The Connection will be taken from the Hibernate Session.
|
||||
* <p>The DataSource specified here should be the target DataSource to manage
|
||||
* transactions for, not a TransactionAwareDataSourceProxy. Only data access
|
||||
* code may work with TransactionAwareDataSourceProxy, while the transaction
|
||||
* manager needs to work on the underlying target DataSource. If there's
|
||||
* nevertheless a TransactionAwareDataSourceProxy passed in, it will be
|
||||
* unwrapped to extract its target DataSource.
|
||||
* @see #setAutodetectDataSource
|
||||
* @see LocalDataSourceConnectionProvider
|
||||
* @see LocalSessionFactoryBean#setDataSource
|
||||
* @see org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy
|
||||
* @see org.springframework.jdbc.datasource.DataSourceUtils
|
||||
* @see org.springframework.jdbc.core.JdbcTemplate
|
||||
*/
|
||||
public void setDataSource(DataSource dataSource) {
|
||||
if (dataSource instanceof TransactionAwareDataSourceProxy) {
|
||||
// If we got a TransactionAwareDataSourceProxy, we need to perform transactions
|
||||
// for its underlying target DataSource, else data access code won't see
|
||||
// properly exposed transactions (i.e. transactions for the target DataSource).
|
||||
this.dataSource = ((TransactionAwareDataSourceProxy) dataSource).getTargetDataSource();
|
||||
}
|
||||
else {
|
||||
this.dataSource = dataSource;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the JDBC DataSource that this instance manages transactions for.
|
||||
*/
|
||||
public DataSource getDataSource() {
|
||||
return this.dataSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether to autodetect a JDBC DataSource used by the Hibernate SessionFactory,
|
||||
* if set via LocalSessionFactoryBean's {@code setDataSource}. Default is "true".
|
||||
* <p>Can be turned off to deliberately ignore an available DataSource, in order
|
||||
* to not expose Hibernate transactions as JDBC transactions for that DataSource.
|
||||
* @see #setDataSource
|
||||
* @see LocalSessionFactoryBean#setDataSource
|
||||
*/
|
||||
public void setAutodetectDataSource(boolean autodetectDataSource) {
|
||||
this.autodetectDataSource = autodetectDataSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether to prepare the underlying JDBC Connection of a transactional
|
||||
* Hibernate Session, that is, whether to apply a transaction-specific
|
||||
* isolation level and/or the transaction's read-only flag to the underlying
|
||||
* JDBC Connection.
|
||||
* <p>Default is "true". If you turn this flag off, the transaction manager
|
||||
* will not support per-transaction isolation levels anymore. It will not
|
||||
* call {@code Connection.setReadOnly(true)} for read-only transactions
|
||||
* anymore either. If this flag is turned off, no cleanup of a JDBC Connection
|
||||
* is required after a transaction, since no Connection settings will get modified.
|
||||
* @see java.sql.Connection#setTransactionIsolation
|
||||
* @see java.sql.Connection#setReadOnly
|
||||
*/
|
||||
public void setPrepareConnection(boolean prepareConnection) {
|
||||
this.prepareConnection = prepareConnection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether to operate on a Hibernate-managed Session instead of a
|
||||
* Spring-managed Session, that is, whether to obtain the Session through
|
||||
* Hibernate's {@link org.hibernate.SessionFactory#getCurrentSession()}
|
||||
* instead of {@link org.hibernate.SessionFactory#openSession()} (with a Spring
|
||||
* {@link org.springframework.transaction.support.TransactionSynchronizationManager}
|
||||
* check preceding it).
|
||||
* <p>Default is "false", i.e. using a Spring-managed Session: taking the current
|
||||
* thread-bound Session if available (e.g. in an Open-Session-in-View scenario),
|
||||
* creating a new Session for the current transaction otherwise.
|
||||
* <p>Switch this flag to "true" in order to enforce use of a Hibernate-managed Session.
|
||||
* Note that this requires {@link org.hibernate.SessionFactory#getCurrentSession()}
|
||||
* to always return a proper Session when called for a Spring-managed transaction;
|
||||
* transaction begin will fail if the {@code getCurrentSession()} call fails.
|
||||
* <p>This mode will typically be used in combination with a custom Hibernate
|
||||
* {@link org.hibernate.context.CurrentSessionContext} implementation that stores
|
||||
* Sessions in a place other than Spring's TransactionSynchronizationManager.
|
||||
* It may also be used in combination with Spring's Open-Session-in-View support
|
||||
* (using Spring's default {@link SpringSessionContext}), in which case it subtly
|
||||
* differs from the Spring-managed Session mode: The pre-bound Session will <i>not</i>
|
||||
* receive a {@code clear()} call (on rollback) or a {@code disconnect()}
|
||||
* call (on transaction completion) in such a scenario; this is rather left up
|
||||
* to a custom CurrentSessionContext implementation (if desired).
|
||||
*/
|
||||
public void setHibernateManagedSession(boolean hibernateManagedSession) {
|
||||
this.hibernateManagedSession = hibernateManagedSession;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether to perform an early flush before proceeding with a commit.
|
||||
* <p>Default is "false", performing an implicit flush as part of the actual
|
||||
* commit step. Switch this to "true" in order to enforce an explicit early
|
||||
* flush right <i>before</i> the actual commit step.
|
||||
* <p>An early flush happens before the before-commit synchronization phase,
|
||||
* making flushed state visible to {@code beforeCommit} callbacks of registered
|
||||
* {@link org.springframework.transaction.support.TransactionSynchronization}
|
||||
* objects. Such explicit flush behavior is consistent with Spring-driven
|
||||
* flushing in a JTA transaction environment, so may also get enforced for
|
||||
* consistency with JTA transaction behavior.
|
||||
* @see #prepareForCommit
|
||||
*/
|
||||
public void setEarlyFlushBeforeCommit(boolean earlyFlushBeforeCommit) {
|
||||
this.earlyFlushBeforeCommit = earlyFlushBeforeCommit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the bean name of a Hibernate entity interceptor that allows to inspect
|
||||
* and change property values before writing to and reading from the database.
|
||||
* Will get applied to any new Session created by this transaction manager.
|
||||
* <p>Requires the bean factory to be known, to be able to resolve the bean
|
||||
* name to an interceptor instance on session creation. Typically used for
|
||||
* prototype interceptors, i.e. a new interceptor instance per session.
|
||||
* <p>Can also be used for shared interceptor instances, but it is recommended
|
||||
* to set the interceptor reference directly in such a scenario.
|
||||
* @param entityInterceptorBeanName the name of the entity interceptor in
|
||||
* the bean factory
|
||||
* @see #setBeanFactory
|
||||
* @see #setEntityInterceptor
|
||||
*/
|
||||
public void setEntityInterceptorBeanName(String entityInterceptorBeanName) {
|
||||
this.entityInterceptor = entityInterceptorBeanName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a Hibernate entity interceptor that allows to inspect and change
|
||||
* property values before writing to and reading from the database.
|
||||
* Will get applied to any new Session created by this transaction manager.
|
||||
* <p>Such an interceptor can either be set at the SessionFactory level,
|
||||
* i.e. on LocalSessionFactoryBean, or at the Session level, i.e. on
|
||||
* HibernateTemplate, HibernateInterceptor, and HibernateTransactionManager.
|
||||
* It's preferable to set it on LocalSessionFactoryBean or HibernateTransactionManager
|
||||
* to avoid repeated configuration and guarantee consistent behavior in transactions.
|
||||
* @see LocalSessionFactoryBean#setEntityInterceptor
|
||||
* @see HibernateTemplate#setEntityInterceptor
|
||||
* @see HibernateInterceptor#setEntityInterceptor
|
||||
*/
|
||||
public void setEntityInterceptor(Interceptor entityInterceptor) {
|
||||
this.entityInterceptor = entityInterceptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current Hibernate entity interceptor, or {@code null} if none.
|
||||
* Resolves an entity interceptor bean name via the bean factory,
|
||||
* if necessary.
|
||||
* @throws IllegalStateException if bean name specified but no bean factory set
|
||||
* @throws BeansException if bean name resolution via the bean factory failed
|
||||
* @see #setEntityInterceptor
|
||||
* @see #setEntityInterceptorBeanName
|
||||
* @see #setBeanFactory
|
||||
*/
|
||||
public Interceptor getEntityInterceptor() throws IllegalStateException, BeansException {
|
||||
if (this.entityInterceptor instanceof Interceptor) {
|
||||
return (Interceptor) entityInterceptor;
|
||||
}
|
||||
else if (this.entityInterceptor instanceof String) {
|
||||
if (this.beanFactory == null) {
|
||||
throw new IllegalStateException("Cannot get entity interceptor via bean name if no bean factory set");
|
||||
}
|
||||
String beanName = (String) this.entityInterceptor;
|
||||
return this.beanFactory.getBean(beanName, Interceptor.class);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the JDBC exception translator for this transaction manager.
|
||||
* <p>Applied to any SQLException root cause of a Hibernate JDBCException that
|
||||
* is thrown on flush, overriding Hibernate's default SQLException translation
|
||||
* (which is based on Hibernate's Dialect for a specific target database).
|
||||
* @param jdbcExceptionTranslator the exception translator
|
||||
* @see java.sql.SQLException
|
||||
* @see org.hibernate.JDBCException
|
||||
* @see org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator
|
||||
* @see org.springframework.jdbc.support.SQLStateSQLExceptionTranslator
|
||||
*/
|
||||
public void setJdbcExceptionTranslator(SQLExceptionTranslator jdbcExceptionTranslator) {
|
||||
this.jdbcExceptionTranslator = jdbcExceptionTranslator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the JDBC exception translator for this transaction manager, if any.
|
||||
*/
|
||||
public SQLExceptionTranslator getJdbcExceptionTranslator() {
|
||||
return this.jdbcExceptionTranslator;
|
||||
}
|
||||
|
||||
/**
|
||||
* The bean factory just needs to be known for resolving entity interceptor
|
||||
* bean names. It does not need to be set for any other mode of operation.
|
||||
* @see #setEntityInterceptorBeanName
|
||||
*/
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
if (getSessionFactory() == null) {
|
||||
throw new IllegalArgumentException("Property 'sessionFactory' is required");
|
||||
}
|
||||
if (this.entityInterceptor instanceof String && this.beanFactory == null) {
|
||||
throw new IllegalArgumentException("Property 'beanFactory' is required for 'entityInterceptorBeanName'");
|
||||
}
|
||||
|
||||
// Check for SessionFactory's DataSource.
|
||||
if (this.autodetectDataSource && getDataSource() == null) {
|
||||
DataSource sfds = SessionFactoryUtils.getDataSource(getSessionFactory());
|
||||
if (sfds != null) {
|
||||
// Use the SessionFactory's DataSource for exposing transactions to JDBC code.
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Using DataSource [" + sfds +
|
||||
"] of Hibernate SessionFactory for HibernateTransactionManager");
|
||||
}
|
||||
setDataSource(sfds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object getResourceFactory() {
|
||||
return getSessionFactory();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object doGetTransaction() {
|
||||
HibernateTransactionObject txObject = new HibernateTransactionObject();
|
||||
txObject.setSavepointAllowed(isNestedTransactionAllowed());
|
||||
|
||||
SessionHolder sessionHolder =
|
||||
(SessionHolder) TransactionSynchronizationManager.getResource(getSessionFactory());
|
||||
if (sessionHolder != null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Found thread-bound Session [" +
|
||||
SessionFactoryUtils.toString(sessionHolder.getSession()) + "] for Hibernate transaction");
|
||||
}
|
||||
txObject.setSessionHolder(sessionHolder);
|
||||
}
|
||||
else if (this.hibernateManagedSession) {
|
||||
try {
|
||||
Session session = getSessionFactory().getCurrentSession();
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Found Hibernate-managed Session [" +
|
||||
SessionFactoryUtils.toString(session) + "] for Spring-managed transaction");
|
||||
}
|
||||
txObject.setExistingSession(session);
|
||||
}
|
||||
catch (HibernateException ex) {
|
||||
throw new DataAccessResourceFailureException(
|
||||
"Could not obtain Hibernate-managed Session for Spring-managed transaction", ex);
|
||||
}
|
||||
}
|
||||
|
||||
if (getDataSource() != null) {
|
||||
ConnectionHolder conHolder = (ConnectionHolder)
|
||||
TransactionSynchronizationManager.getResource(getDataSource());
|
||||
txObject.setConnectionHolder(conHolder);
|
||||
}
|
||||
|
||||
return txObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isExistingTransaction(Object transaction) {
|
||||
HibernateTransactionObject txObject = (HibernateTransactionObject) transaction;
|
||||
return (txObject.hasSpringManagedTransaction() ||
|
||||
(this.hibernateManagedSession && txObject.hasHibernateManagedTransaction()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doBegin(Object transaction, TransactionDefinition definition) {
|
||||
HibernateTransactionObject txObject = (HibernateTransactionObject) transaction;
|
||||
|
||||
if (txObject.hasConnectionHolder() && !txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
|
||||
throw new IllegalTransactionStateException(
|
||||
"Pre-bound JDBC Connection found! HibernateTransactionManager does not support " +
|
||||
"running within DataSourceTransactionManager if told to manage the DataSource itself. " +
|
||||
"It is recommended to use a single HibernateTransactionManager for all transactions " +
|
||||
"on a single DataSource, no matter whether Hibernate or JDBC access.");
|
||||
}
|
||||
|
||||
Session session = null;
|
||||
|
||||
try {
|
||||
if (txObject.getSessionHolder() == null || txObject.getSessionHolder().isSynchronizedWithTransaction()) {
|
||||
Interceptor entityInterceptor = getEntityInterceptor();
|
||||
Session newSession = (entityInterceptor != null ?
|
||||
getSessionFactory().openSession(entityInterceptor) : getSessionFactory().openSession());
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Opened new Session [" + SessionFactoryUtils.toString(newSession) +
|
||||
"] for Hibernate transaction");
|
||||
}
|
||||
txObject.setSession(newSession);
|
||||
}
|
||||
|
||||
session = txObject.getSessionHolder().getSession();
|
||||
|
||||
if (this.prepareConnection && isSameConnectionForEntireSession(session)) {
|
||||
// We're allowed to change the transaction settings of the JDBC Connection.
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(
|
||||
"Preparing JDBC Connection of Hibernate Session [" + SessionFactoryUtils.toString(session) + "]");
|
||||
}
|
||||
Connection con = session.connection();
|
||||
Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
|
||||
txObject.setPreviousIsolationLevel(previousIsolationLevel);
|
||||
}
|
||||
else {
|
||||
// Not allowed to change the transaction settings of the JDBC Connection.
|
||||
if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) {
|
||||
// We should set a specific isolation level but are not allowed to...
|
||||
throw new InvalidIsolationLevelException(
|
||||
"HibernateTransactionManager is not allowed to support custom isolation levels: " +
|
||||
"make sure that its 'prepareConnection' flag is on (the default) and that the " +
|
||||
"Hibernate connection release mode is set to 'on_close' (SpringTransactionFactory's default). " +
|
||||
"Make sure that your LocalSessionFactoryBean actually uses SpringTransactionFactory: Your " +
|
||||
"Hibernate properties should *not* include a 'hibernate.transaction.factory_class' property!");
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(
|
||||
"Not preparing JDBC Connection of Hibernate Session [" + SessionFactoryUtils.toString(session) + "]");
|
||||
}
|
||||
}
|
||||
|
||||
if (definition.isReadOnly() && txObject.isNewSession()) {
|
||||
// Just set to MANUAL in case of a new Session for this transaction.
|
||||
session.setFlushMode(FlushMode.MANUAL);
|
||||
}
|
||||
|
||||
if (!definition.isReadOnly() && !txObject.isNewSession()) {
|
||||
// We need AUTO or COMMIT for a non-read-only transaction.
|
||||
FlushMode flushMode = session.getFlushMode();
|
||||
if (flushMode.lessThan(FlushMode.COMMIT)) {
|
||||
session.setFlushMode(FlushMode.AUTO);
|
||||
txObject.getSessionHolder().setPreviousFlushMode(flushMode);
|
||||
}
|
||||
}
|
||||
|
||||
Transaction hibTx;
|
||||
|
||||
// Register transaction timeout.
|
||||
int timeout = determineTimeout(definition);
|
||||
if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
|
||||
// Use Hibernate's own transaction timeout mechanism on Hibernate 3.1+
|
||||
// Applies to all statements, also to inserts, updates and deletes!
|
||||
hibTx = session.getTransaction();
|
||||
hibTx.setTimeout(timeout);
|
||||
hibTx.begin();
|
||||
}
|
||||
else {
|
||||
// Open a plain Hibernate transaction without specified timeout.
|
||||
hibTx = session.beginTransaction();
|
||||
}
|
||||
|
||||
// Add the Hibernate transaction to the session holder.
|
||||
txObject.getSessionHolder().setTransaction(hibTx);
|
||||
|
||||
// Register the Hibernate Session's JDBC Connection for the DataSource, if set.
|
||||
if (getDataSource() != null) {
|
||||
Connection con = session.connection();
|
||||
ConnectionHolder conHolder = new ConnectionHolder(con);
|
||||
if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
|
||||
conHolder.setTimeoutInSeconds(timeout);
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Exposing Hibernate transaction as JDBC transaction [" + con + "]");
|
||||
}
|
||||
TransactionSynchronizationManager.bindResource(getDataSource(), conHolder);
|
||||
txObject.setConnectionHolder(conHolder);
|
||||
}
|
||||
|
||||
// Bind the session holder to the thread.
|
||||
if (txObject.isNewSessionHolder()) {
|
||||
TransactionSynchronizationManager.bindResource(getSessionFactory(), txObject.getSessionHolder());
|
||||
}
|
||||
txObject.getSessionHolder().setSynchronizedWithTransaction(true);
|
||||
}
|
||||
|
||||
catch (Throwable ex) {
|
||||
if (txObject.isNewSession()) {
|
||||
try {
|
||||
if (session.getTransaction().isActive()) {
|
||||
session.getTransaction().rollback();
|
||||
}
|
||||
}
|
||||
catch (Throwable ex2) {
|
||||
logger.debug("Could not rollback Session after failed transaction begin", ex);
|
||||
}
|
||||
finally {
|
||||
SessionFactoryUtils.closeSession(session);
|
||||
txObject.setSessionHolder(null);
|
||||
}
|
||||
}
|
||||
throw new CannotCreateTransactionException("Could not open Hibernate Session for transaction", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object doSuspend(Object transaction) {
|
||||
HibernateTransactionObject txObject = (HibernateTransactionObject) transaction;
|
||||
txObject.setSessionHolder(null);
|
||||
SessionHolder sessionHolder =
|
||||
(SessionHolder) TransactionSynchronizationManager.unbindResource(getSessionFactory());
|
||||
txObject.setConnectionHolder(null);
|
||||
ConnectionHolder connectionHolder = null;
|
||||
if (getDataSource() != null) {
|
||||
connectionHolder = (ConnectionHolder) TransactionSynchronizationManager.unbindResource(getDataSource());
|
||||
}
|
||||
return new SuspendedResourcesHolder(sessionHolder, connectionHolder);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doResume(Object transaction, Object suspendedResources) {
|
||||
SuspendedResourcesHolder resourcesHolder = (SuspendedResourcesHolder) suspendedResources;
|
||||
if (TransactionSynchronizationManager.hasResource(getSessionFactory())) {
|
||||
// From non-transactional code running in active transaction synchronization
|
||||
// -> can be safely removed, will be closed on transaction completion.
|
||||
TransactionSynchronizationManager.unbindResource(getSessionFactory());
|
||||
}
|
||||
TransactionSynchronizationManager.bindResource(getSessionFactory(), resourcesHolder.getSessionHolder());
|
||||
if (getDataSource() != null) {
|
||||
TransactionSynchronizationManager.bindResource(getDataSource(), resourcesHolder.getConnectionHolder());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void prepareForCommit(DefaultTransactionStatus status) {
|
||||
if (this.earlyFlushBeforeCommit && status.isNewTransaction()) {
|
||||
HibernateTransactionObject txObject = (HibernateTransactionObject) status.getTransaction();
|
||||
Session session = txObject.getSessionHolder().getSession();
|
||||
if (!session.getFlushMode().lessThan(FlushMode.COMMIT)) {
|
||||
logger.debug("Performing an early flush for Hibernate transaction");
|
||||
try {
|
||||
session.flush();
|
||||
}
|
||||
catch (HibernateException ex) {
|
||||
throw convertHibernateAccessException(ex);
|
||||
}
|
||||
finally {
|
||||
session.setFlushMode(FlushMode.MANUAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doCommit(DefaultTransactionStatus status) {
|
||||
HibernateTransactionObject txObject = (HibernateTransactionObject) status.getTransaction();
|
||||
if (status.isDebug()) {
|
||||
logger.debug("Committing Hibernate transaction on Session [" +
|
||||
SessionFactoryUtils.toString(txObject.getSessionHolder().getSession()) + "]");
|
||||
}
|
||||
try {
|
||||
txObject.getSessionHolder().getTransaction().commit();
|
||||
}
|
||||
catch (org.hibernate.TransactionException ex) {
|
||||
// assumably from commit call to the underlying JDBC connection
|
||||
throw new TransactionSystemException("Could not commit Hibernate transaction", ex);
|
||||
}
|
||||
catch (HibernateException ex) {
|
||||
// assumably failed to flush changes to database
|
||||
throw convertHibernateAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doRollback(DefaultTransactionStatus status) {
|
||||
HibernateTransactionObject txObject = (HibernateTransactionObject) status.getTransaction();
|
||||
if (status.isDebug()) {
|
||||
logger.debug("Rolling back Hibernate transaction on Session [" +
|
||||
SessionFactoryUtils.toString(txObject.getSessionHolder().getSession()) + "]");
|
||||
}
|
||||
try {
|
||||
txObject.getSessionHolder().getTransaction().rollback();
|
||||
}
|
||||
catch (org.hibernate.TransactionException ex) {
|
||||
throw new TransactionSystemException("Could not roll back Hibernate transaction", ex);
|
||||
}
|
||||
catch (HibernateException ex) {
|
||||
// Shouldn't really happen, as a rollback doesn't cause a flush.
|
||||
throw convertHibernateAccessException(ex);
|
||||
}
|
||||
finally {
|
||||
if (!txObject.isNewSession() && !this.hibernateManagedSession) {
|
||||
// Clear all pending inserts/updates/deletes in the Session.
|
||||
// Necessary for pre-bound Sessions, to avoid inconsistent state.
|
||||
txObject.getSessionHolder().getSession().clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doSetRollbackOnly(DefaultTransactionStatus status) {
|
||||
HibernateTransactionObject txObject = (HibernateTransactionObject) status.getTransaction();
|
||||
if (status.isDebug()) {
|
||||
logger.debug("Setting Hibernate transaction on Session [" +
|
||||
SessionFactoryUtils.toString(txObject.getSessionHolder().getSession()) + "] rollback-only");
|
||||
}
|
||||
txObject.setRollbackOnly();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doCleanupAfterCompletion(Object transaction) {
|
||||
HibernateTransactionObject txObject = (HibernateTransactionObject) transaction;
|
||||
|
||||
// Remove the session holder from the thread.
|
||||
if (txObject.isNewSessionHolder()) {
|
||||
TransactionSynchronizationManager.unbindResource(getSessionFactory());
|
||||
}
|
||||
|
||||
// Remove the JDBC connection holder from the thread, if exposed.
|
||||
if (getDataSource() != null) {
|
||||
TransactionSynchronizationManager.unbindResource(getDataSource());
|
||||
}
|
||||
|
||||
Session session = txObject.getSessionHolder().getSession();
|
||||
if (this.prepareConnection && session.isConnected() && isSameConnectionForEntireSession(session)) {
|
||||
// We're running with connection release mode "on_close": We're able to reset
|
||||
// the isolation level and/or read-only flag of the JDBC Connection here.
|
||||
// Else, we need to rely on the connection pool to perform proper cleanup.
|
||||
try {
|
||||
Connection con = session.connection();
|
||||
DataSourceUtils.resetConnectionAfterTransaction(con, txObject.getPreviousIsolationLevel());
|
||||
}
|
||||
catch (HibernateException ex) {
|
||||
logger.debug("Could not access JDBC Connection of Hibernate Session", ex);
|
||||
}
|
||||
}
|
||||
|
||||
if (txObject.isNewSession()) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Closing Hibernate Session [" + SessionFactoryUtils.toString(session) +
|
||||
"] after transaction");
|
||||
}
|
||||
SessionFactoryUtils.closeSessionOrRegisterDeferredClose(session, getSessionFactory());
|
||||
}
|
||||
else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Not closing pre-bound Hibernate Session [" +
|
||||
SessionFactoryUtils.toString(session) + "] after transaction");
|
||||
}
|
||||
if (txObject.getSessionHolder().getPreviousFlushMode() != null) {
|
||||
session.setFlushMode(txObject.getSessionHolder().getPreviousFlushMode());
|
||||
}
|
||||
if (!this.hibernateManagedSession) {
|
||||
session.disconnect();
|
||||
}
|
||||
}
|
||||
txObject.getSessionHolder().clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the given Hibernate Session will always hold the same
|
||||
* JDBC Connection. This is used to check whether the transaction manager
|
||||
* can safely prepare and clean up the JDBC Connection used for a transaction.
|
||||
* <p>Default implementation checks the Session's connection release mode
|
||||
* to be "on_close". Unfortunately, this requires casting to SessionImpl,
|
||||
* as of Hibernate 3.1. If that cast doesn't work, we'll simply assume
|
||||
* we're safe and return {@code true}.
|
||||
* @param session the Hibernate Session to check
|
||||
* @see org.hibernate.impl.SessionImpl#getConnectionReleaseMode()
|
||||
* @see org.hibernate.ConnectionReleaseMode#ON_CLOSE
|
||||
*/
|
||||
protected boolean isSameConnectionForEntireSession(Session session) {
|
||||
if (!(session instanceof SessionImpl)) {
|
||||
// The best we can do is to assume we're safe.
|
||||
return true;
|
||||
}
|
||||
ConnectionReleaseMode releaseMode = ((SessionImpl) session).getConnectionReleaseMode();
|
||||
return ConnectionReleaseMode.ON_CLOSE.equals(releaseMode);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert the given HibernateException to an appropriate exception
|
||||
* from the {@code org.springframework.dao} hierarchy.
|
||||
* <p>Will automatically apply a specified SQLExceptionTranslator to a
|
||||
* Hibernate JDBCException, else rely on Hibernate's default translation.
|
||||
* @param ex HibernateException that occurred
|
||||
* @return a corresponding DataAccessException
|
||||
* @see SessionFactoryUtils#convertHibernateAccessException
|
||||
* @see #setJdbcExceptionTranslator
|
||||
*/
|
||||
protected DataAccessException convertHibernateAccessException(HibernateException ex) {
|
||||
if (getJdbcExceptionTranslator() != null && ex instanceof JDBCException) {
|
||||
return convertJdbcAccessException((JDBCException) ex, getJdbcExceptionTranslator());
|
||||
}
|
||||
else if (GenericJDBCException.class == ex.getClass()) {
|
||||
return convertJdbcAccessException((GenericJDBCException) ex, getDefaultJdbcExceptionTranslator());
|
||||
}
|
||||
return SessionFactoryUtils.convertHibernateAccessException(ex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given Hibernate JDBCException to an appropriate exception
|
||||
* from the {@code org.springframework.dao} hierarchy, using the
|
||||
* given SQLExceptionTranslator.
|
||||
* @param ex Hibernate JDBCException that occurred
|
||||
* @param translator the SQLExceptionTranslator to use
|
||||
* @return a corresponding DataAccessException
|
||||
*/
|
||||
protected DataAccessException convertJdbcAccessException(JDBCException ex, SQLExceptionTranslator translator) {
|
||||
return translator.translate("Hibernate flushing: " + ex.getMessage(), ex.getSQL(), ex.getSQLException());
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain a default SQLExceptionTranslator, lazily creating it if necessary.
|
||||
* <p>Creates a default
|
||||
* {@link org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator}
|
||||
* for the SessionFactory's underlying DataSource.
|
||||
*/
|
||||
protected synchronized SQLExceptionTranslator getDefaultJdbcExceptionTranslator() {
|
||||
if (this.defaultJdbcExceptionTranslator == null) {
|
||||
if (getDataSource() != null) {
|
||||
this.defaultJdbcExceptionTranslator = new SQLErrorCodeSQLExceptionTranslator(getDataSource());
|
||||
}
|
||||
else {
|
||||
this.defaultJdbcExceptionTranslator = SessionFactoryUtils.newJdbcExceptionTranslator(getSessionFactory());
|
||||
}
|
||||
}
|
||||
return this.defaultJdbcExceptionTranslator;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Hibernate transaction object, representing a SessionHolder.
|
||||
* Used as transaction object by HibernateTransactionManager.
|
||||
*/
|
||||
private class HibernateTransactionObject extends JdbcTransactionObjectSupport {
|
||||
|
||||
private SessionHolder sessionHolder;
|
||||
|
||||
private boolean newSessionHolder;
|
||||
|
||||
private boolean newSession;
|
||||
|
||||
public void setSession(Session session) {
|
||||
this.sessionHolder = new SessionHolder(session);
|
||||
this.newSessionHolder = true;
|
||||
this.newSession = true;
|
||||
}
|
||||
|
||||
public void setExistingSession(Session session) {
|
||||
this.sessionHolder = new SessionHolder(session);
|
||||
this.newSessionHolder = true;
|
||||
this.newSession = false;
|
||||
}
|
||||
|
||||
public void setSessionHolder(SessionHolder sessionHolder) {
|
||||
this.sessionHolder = sessionHolder;
|
||||
this.newSessionHolder = false;
|
||||
this.newSession = false;
|
||||
}
|
||||
|
||||
public SessionHolder getSessionHolder() {
|
||||
return this.sessionHolder;
|
||||
}
|
||||
|
||||
public boolean isNewSessionHolder() {
|
||||
return this.newSessionHolder;
|
||||
}
|
||||
|
||||
public boolean isNewSession() {
|
||||
return this.newSession;
|
||||
}
|
||||
|
||||
public boolean hasSpringManagedTransaction() {
|
||||
return (this.sessionHolder != null && this.sessionHolder.getTransaction() != null);
|
||||
}
|
||||
|
||||
public boolean hasHibernateManagedTransaction() {
|
||||
return (this.sessionHolder != null && this.sessionHolder.getSession().getTransaction().isActive());
|
||||
}
|
||||
|
||||
public void setRollbackOnly() {
|
||||
this.sessionHolder.setRollbackOnly();
|
||||
if (hasConnectionHolder()) {
|
||||
getConnectionHolder().setRollbackOnly();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRollbackOnly() {
|
||||
return this.sessionHolder.isRollbackOnly() ||
|
||||
(hasConnectionHolder() && getConnectionHolder().isRollbackOnly());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() {
|
||||
try {
|
||||
this.sessionHolder.getSession().flush();
|
||||
}
|
||||
catch (HibernateException ex) {
|
||||
throw convertHibernateAccessException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Holder for suspended resources.
|
||||
* Used internally by {@code doSuspend} and {@code doResume}.
|
||||
*/
|
||||
private static class SuspendedResourcesHolder {
|
||||
|
||||
private final SessionHolder sessionHolder;
|
||||
|
||||
private final ConnectionHolder connectionHolder;
|
||||
|
||||
private SuspendedResourcesHolder(SessionHolder sessionHolder, ConnectionHolder conHolder) {
|
||||
this.sessionHolder = sessionHolder;
|
||||
this.connectionHolder = conHolder;
|
||||
}
|
||||
|
||||
private SessionHolder getSessionHolder() {
|
||||
return this.sessionHolder;
|
||||
}
|
||||
|
||||
private ConnectionHolder getConnectionHolder() {
|
||||
return this.connectionHolder;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,128 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate3;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Properties;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.connection.ConnectionProvider;
|
||||
import org.hibernate.util.JDBCExceptionReporter;
|
||||
|
||||
import org.springframework.jdbc.datasource.DataSourceUtils;
|
||||
|
||||
/**
|
||||
* Hibernate connection provider for local DataSource instances
|
||||
* in an application context. This provider will be used if
|
||||
* LocalSessionFactoryBean's "dataSource" property is set
|
||||
* without a Hibernate TransactionManagerLookup.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @see LocalSessionFactoryBean#setDataSource
|
||||
* @deprecated as of Spring 4.3, in favor of Hibernate 4.x/5.x
|
||||
*/
|
||||
@Deprecated
|
||||
public class LocalDataSourceConnectionProvider implements ConnectionProvider {
|
||||
|
||||
private DataSource dataSource;
|
||||
|
||||
private DataSource dataSourceToUse;
|
||||
|
||||
|
||||
@Override
|
||||
public void configure(Properties props) throws HibernateException {
|
||||
this.dataSource = LocalSessionFactoryBean.getConfigTimeDataSource();
|
||||
// absolutely needs thread-bound DataSource to initialize
|
||||
if (this.dataSource == null) {
|
||||
throw new HibernateException("No local DataSource found for configuration - " +
|
||||
"'dataSource' property must be set on LocalSessionFactoryBean");
|
||||
}
|
||||
this.dataSourceToUse = getDataSourceToUse(this.dataSource);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the DataSource to use for retrieving Connections.
|
||||
* <p>This implementation returns the passed-in DataSource as-is.
|
||||
* @param originalDataSource the DataSource as configured by the user
|
||||
* on LocalSessionFactoryBean
|
||||
* @return the DataSource to actually retrieve Connections from
|
||||
* (potentially wrapped)
|
||||
* @see LocalSessionFactoryBean#setDataSource
|
||||
*/
|
||||
protected DataSource getDataSourceToUse(DataSource originalDataSource) {
|
||||
return originalDataSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the DataSource that this ConnectionProvider wraps.
|
||||
*/
|
||||
public DataSource getDataSource() {
|
||||
return this.dataSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation delegates to the underlying DataSource.
|
||||
* @see javax.sql.DataSource#getConnection()
|
||||
*/
|
||||
@Override
|
||||
public Connection getConnection() throws SQLException {
|
||||
try {
|
||||
return this.dataSourceToUse.getConnection();
|
||||
}
|
||||
catch (SQLException ex) {
|
||||
JDBCExceptionReporter.logExceptions(ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation calls {@link DataSourceUtils#doCloseConnection},
|
||||
* checking against a {@link org.springframework.jdbc.datasource.SmartDataSource}.
|
||||
*/
|
||||
@Override
|
||||
public void closeConnection(Connection con) throws SQLException {
|
||||
try {
|
||||
DataSourceUtils.doCloseConnection(con, this.dataSourceToUse);
|
||||
}
|
||||
catch (SQLException ex) {
|
||||
JDBCExceptionReporter.logExceptions(ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation does nothing:
|
||||
* We're dealing with an externally managed DataSource.
|
||||
*/
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation returns {@code false}: We cannot guarantee
|
||||
* to receive the same Connection within a transaction, not even when
|
||||
* dealing with a JNDI DataSource.
|
||||
*/
|
||||
@Override
|
||||
public boolean supportsAggressiveRelease() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate3;
|
||||
|
||||
/**
|
||||
* Subclass of LocalDataSourceConnectionProvider that will be used
|
||||
* if LocalSessionFactoryBean's "dataSource" property is set
|
||||
* in combination with a Hibernate TransactionManagerLookup.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.5.1
|
||||
* @deprecated as of Spring 4.3, in favor of Hibernate 4.x/5.x
|
||||
*/
|
||||
@Deprecated
|
||||
public class LocalJtaDataSourceConnectionProvider extends LocalDataSourceConnectionProvider {
|
||||
|
||||
/**
|
||||
* This implementation returns {@code true},
|
||||
* since we're assuming a JTA DataSource.
|
||||
*/
|
||||
@Override
|
||||
public boolean supportsAggressiveRelease() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,122 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate3;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.hibernate.cache.CacheDataDescription;
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.CollectionRegion;
|
||||
import org.hibernate.cache.EntityRegion;
|
||||
import org.hibernate.cache.QueryResultsRegion;
|
||||
import org.hibernate.cache.RegionFactory;
|
||||
import org.hibernate.cache.TimestampsRegion;
|
||||
import org.hibernate.cache.access.AccessType;
|
||||
import org.hibernate.cfg.Settings;
|
||||
|
||||
/**
|
||||
* Proxy for a Hibernate RegionFactory, delegating to a Spring-managed
|
||||
* RegionFactory instance, determined by LocalSessionFactoryBean's
|
||||
* "cacheRegionFactory" property.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
* @see LocalSessionFactoryBean#setCacheRegionFactory
|
||||
* @deprecated as of Spring 4.3, in favor of Hibernate 4.x/5.x
|
||||
*/
|
||||
@Deprecated
|
||||
public class LocalRegionFactoryProxy implements RegionFactory {
|
||||
|
||||
private final RegionFactory regionFactory;
|
||||
|
||||
|
||||
/**
|
||||
* Standard constructor.
|
||||
*/
|
||||
public LocalRegionFactoryProxy() {
|
||||
RegionFactory rf = (RegionFactory) LocalSessionFactoryBean.getConfigTimeRegionFactory();
|
||||
// absolutely needs thread-bound RegionFactory to initialize
|
||||
if (rf == null) {
|
||||
throw new IllegalStateException("No Hibernate RegionFactory found - " +
|
||||
"'cacheRegionFactory' property must be set on LocalSessionFactoryBean");
|
||||
}
|
||||
this.regionFactory = rf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Properties constructor: not used by this class or formally required,
|
||||
* but enforced by Hibernate when reflectively instantiating a RegionFactory.
|
||||
*/
|
||||
public LocalRegionFactoryProxy(Properties properties) {
|
||||
this();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void start(Settings settings, Properties properties) throws CacheException {
|
||||
this.regionFactory.start(settings, properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
this.regionFactory.stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMinimalPutsEnabledByDefault() {
|
||||
return this.regionFactory.isMinimalPutsEnabledByDefault();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessType getDefaultAccessType() {
|
||||
return this.regionFactory.getDefaultAccessType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long nextTimestamp() {
|
||||
return this.regionFactory.nextTimestamp();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityRegion buildEntityRegion(String regionName, Properties properties, CacheDataDescription metadata)
|
||||
throws CacheException {
|
||||
|
||||
return this.regionFactory.buildEntityRegion(regionName, properties, metadata);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollectionRegion buildCollectionRegion(String regionName, Properties properties,
|
||||
CacheDataDescription metadata) throws CacheException {
|
||||
|
||||
return this.regionFactory.buildCollectionRegion(regionName, properties, metadata);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryResultsRegion buildQueryResultsRegion(String regionName, Properties properties)
|
||||
throws CacheException {
|
||||
|
||||
return this.regionFactory.buildQueryResultsRegion(regionName, properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TimestampsRegion buildTimestampsRegion(String regionName, Properties properties)
|
||||
throws CacheException {
|
||||
|
||||
return this.regionFactory.buildTimestampsRegion(regionName, properties);
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,77 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate3;
|
||||
|
||||
import java.util.Properties;
|
||||
import javax.transaction.Transaction;
|
||||
import javax.transaction.TransactionManager;
|
||||
|
||||
import org.hibernate.transaction.TransactionManagerLookup;
|
||||
|
||||
/**
|
||||
* Implementation of Hibernate's {@link TransactionManagerLookup} interface
|
||||
* that returns a Spring-managed JTA {@link TransactionManager}, determined
|
||||
* by LocalSessionFactoryBean's "jtaTransactionManager" property.
|
||||
*
|
||||
* <p>The main advantage of this TransactionManagerLookup is that it avoids
|
||||
* double configuration of JTA specifics. A single TransactionManager bean can
|
||||
* be used for both JtaTransactionManager and LocalSessionFactoryBean, with no
|
||||
* JTA setup in Hibernate configuration.
|
||||
*
|
||||
* <p>Alternatively, use Hibernate's own TransactionManagerLookup implementations:
|
||||
* Spring's JtaTransactionManager only requires a TransactionManager for suspending
|
||||
* and resuming transactions, so you might not need to apply such special Spring
|
||||
* configuration at all.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @see LocalSessionFactoryBean#setJtaTransactionManager
|
||||
* @see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager
|
||||
* @deprecated as of Spring 4.3, in favor of Hibernate 4.x/5.x
|
||||
*/
|
||||
@Deprecated
|
||||
public class LocalTransactionManagerLookup implements TransactionManagerLookup {
|
||||
|
||||
private final TransactionManager transactionManager;
|
||||
|
||||
|
||||
public LocalTransactionManagerLookup() {
|
||||
TransactionManager tm = LocalSessionFactoryBean.getConfigTimeTransactionManager();
|
||||
// absolutely needs thread-bound TransactionManager to initialize
|
||||
if (tm == null) {
|
||||
throw new IllegalStateException("No JTA TransactionManager found - " +
|
||||
"'jtaTransactionManager' property must be set on LocalSessionFactoryBean");
|
||||
}
|
||||
this.transactionManager = tm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransactionManager getTransactionManager(Properties props) {
|
||||
return this.transactionManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUserTransactionName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getTransactionIdentifier(Transaction transaction) {
|
||||
return transaction;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,832 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate3;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.sql.DataSource;
|
||||
import javax.transaction.Status;
|
||||
import javax.transaction.Transaction;
|
||||
import javax.transaction.TransactionManager;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.FlushMode;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.Interceptor;
|
||||
import org.hibernate.JDBCException;
|
||||
import org.hibernate.NonUniqueObjectException;
|
||||
import org.hibernate.NonUniqueResultException;
|
||||
import org.hibernate.ObjectDeletedException;
|
||||
import org.hibernate.OptimisticLockException;
|
||||
import org.hibernate.PersistentObjectException;
|
||||
import org.hibernate.PessimisticLockException;
|
||||
import org.hibernate.PropertyValueException;
|
||||
import org.hibernate.Query;
|
||||
import org.hibernate.QueryException;
|
||||
import org.hibernate.QueryTimeoutException;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.StaleObjectStateException;
|
||||
import org.hibernate.StaleStateException;
|
||||
import org.hibernate.TransientObjectException;
|
||||
import org.hibernate.UnresolvableObjectException;
|
||||
import org.hibernate.WrongClassException;
|
||||
import org.hibernate.connection.ConnectionProvider;
|
||||
import org.hibernate.engine.SessionFactoryImplementor;
|
||||
import org.hibernate.exception.ConstraintViolationException;
|
||||
import org.hibernate.exception.DataException;
|
||||
import org.hibernate.exception.JDBCConnectionException;
|
||||
import org.hibernate.exception.LockAcquisitionException;
|
||||
import org.hibernate.exception.SQLGrammarException;
|
||||
|
||||
import org.springframework.core.NamedThreadLocal;
|
||||
import org.springframework.dao.CannotAcquireLockException;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.DataAccessResourceFailureException;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.dao.IncorrectResultSizeDataAccessException;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.dao.InvalidDataAccessResourceUsageException;
|
||||
import org.springframework.dao.PessimisticLockingFailureException;
|
||||
import org.springframework.jdbc.datasource.DataSourceUtils;
|
||||
import org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator;
|
||||
import org.springframework.jdbc.support.SQLExceptionTranslator;
|
||||
import org.springframework.jdbc.support.SQLStateSQLExceptionTranslator;
|
||||
import org.springframework.transaction.jta.SpringJtaSynchronizationAdapter;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Helper class featuring methods for Hibernate Session handling,
|
||||
* allowing for reuse of Hibernate Session instances within transactions.
|
||||
* Also provides support for exception translation.
|
||||
*
|
||||
* <p>Supports synchronization with both Spring-managed JTA transactions
|
||||
* (see {@link org.springframework.transaction.jta.JtaTransactionManager})
|
||||
* and non-Spring JTA transactions (i.e. plain JTA or EJB CMT),
|
||||
* transparently providing transaction-scoped Hibernate Sessions.
|
||||
* Note that for non-Spring JTA transactions, a JTA TransactionManagerLookup
|
||||
* has to be specified in the Hibernate configuration.
|
||||
*
|
||||
* <p>Used internally by {@link HibernateTemplate}, {@link HibernateInterceptor}
|
||||
* and {@link HibernateTransactionManager}. Can also be used directly in
|
||||
* application code.
|
||||
*
|
||||
* <p>Requires Hibernate 3.6.x, as of Spring 4.0.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @see #getSession
|
||||
* @see #releaseSession
|
||||
* @see HibernateTransactionManager
|
||||
* @see org.springframework.transaction.jta.JtaTransactionManager
|
||||
* @see org.springframework.transaction.support.TransactionSynchronizationManager
|
||||
* @deprecated as of Spring 4.3, in favor of Hibernate 4.x/5.x
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract class SessionFactoryUtils {
|
||||
|
||||
/**
|
||||
* Order value for TransactionSynchronization objects that clean up Hibernate Sessions.
|
||||
* Returns {@code DataSourceUtils.CONNECTION_SYNCHRONIZATION_ORDER - 100}
|
||||
* to execute Session cleanup before JDBC Connection cleanup, if any.
|
||||
* @see org.springframework.jdbc.datasource.DataSourceUtils#CONNECTION_SYNCHRONIZATION_ORDER
|
||||
*/
|
||||
public static final int SESSION_SYNCHRONIZATION_ORDER =
|
||||
DataSourceUtils.CONNECTION_SYNCHRONIZATION_ORDER - 100;
|
||||
|
||||
static final Log logger = LogFactory.getLog(SessionFactoryUtils.class);
|
||||
|
||||
private static final ThreadLocal<Map<SessionFactory, Set<Session>>> deferredCloseHolder =
|
||||
new NamedThreadLocal<Map<SessionFactory, Set<Session>>>("Hibernate Sessions registered for deferred close");
|
||||
|
||||
|
||||
/**
|
||||
* Determine the DataSource of the given SessionFactory.
|
||||
* @param sessionFactory the SessionFactory to check
|
||||
* @return the DataSource, or {@code null} if none found
|
||||
* @see org.hibernate.engine.SessionFactoryImplementor#getConnectionProvider
|
||||
* @see LocalDataSourceConnectionProvider
|
||||
*/
|
||||
public static DataSource getDataSource(SessionFactory sessionFactory) {
|
||||
if (sessionFactory instanceof SessionFactoryImplementor) {
|
||||
ConnectionProvider cp = ((SessionFactoryImplementor) sessionFactory).getConnectionProvider();
|
||||
if (cp instanceof LocalDataSourceConnectionProvider) {
|
||||
return ((LocalDataSourceConnectionProvider) cp).getDataSource();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an appropriate SQLExceptionTranslator for the given SessionFactory.
|
||||
* If a DataSource is found, a SQLErrorCodeSQLExceptionTranslator for the DataSource
|
||||
* is created; else, a SQLStateSQLExceptionTranslator as fallback.
|
||||
* @param sessionFactory the SessionFactory to create the translator for
|
||||
* @return the SQLExceptionTranslator
|
||||
* @see #getDataSource
|
||||
* @see org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator
|
||||
* @see org.springframework.jdbc.support.SQLStateSQLExceptionTranslator
|
||||
*/
|
||||
public static SQLExceptionTranslator newJdbcExceptionTranslator(SessionFactory sessionFactory) {
|
||||
DataSource ds = getDataSource(sessionFactory);
|
||||
if (ds != null) {
|
||||
return new SQLErrorCodeSQLExceptionTranslator(ds);
|
||||
}
|
||||
return new SQLStateSQLExceptionTranslator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to retrieve the JTA TransactionManager from the given SessionFactory
|
||||
* and/or Session. Check the passed-in SessionFactory for implementing
|
||||
* SessionFactoryImplementor (the usual case), falling back to the
|
||||
* SessionFactory reference that the Session itself carries.
|
||||
* @param sessionFactory Hibernate SessionFactory
|
||||
* @param session Hibernate Session (can also be {@code null})
|
||||
* @return the JTA TransactionManager, if any
|
||||
* @see javax.transaction.TransactionManager
|
||||
* @see SessionFactoryImplementor#getTransactionManager
|
||||
* @see Session#getSessionFactory
|
||||
* @see org.hibernate.impl.SessionFactoryImpl
|
||||
*/
|
||||
public static TransactionManager getJtaTransactionManager(SessionFactory sessionFactory, Session session) {
|
||||
SessionFactoryImplementor sessionFactoryImpl = null;
|
||||
if (sessionFactory instanceof SessionFactoryImplementor) {
|
||||
sessionFactoryImpl = ((SessionFactoryImplementor) sessionFactory);
|
||||
}
|
||||
else if (session != null) {
|
||||
SessionFactory internalFactory = session.getSessionFactory();
|
||||
if (internalFactory instanceof SessionFactoryImplementor) {
|
||||
sessionFactoryImpl = (SessionFactoryImplementor) internalFactory;
|
||||
}
|
||||
}
|
||||
return (sessionFactoryImpl != null ? sessionFactoryImpl.getTransactionManager() : null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a Hibernate Session for the given SessionFactory. Is aware of and will
|
||||
* return any existing corresponding Session bound to the current thread, for
|
||||
* example when using {@link HibernateTransactionManager}. Will create a new
|
||||
* Session otherwise, if "allowCreate" is {@code true}.
|
||||
* <p>This is the {@code getSession} method used by typical data access code,
|
||||
* in combination with {@code releaseSession} called when done with
|
||||
* the Session. Note that HibernateTemplate allows to write data access code
|
||||
* without caring about such resource handling.
|
||||
* @param sessionFactory Hibernate SessionFactory to create the session with
|
||||
* @param allowCreate whether a non-transactional Session should be created
|
||||
* when no transactional Session can be found for the current thread
|
||||
* @return the Hibernate Session
|
||||
* @throws DataAccessResourceFailureException if the Session couldn't be created
|
||||
* @throws IllegalStateException if no thread-bound Session found and
|
||||
* "allowCreate" is {@code false}
|
||||
* @see #getSession(SessionFactory, Interceptor, SQLExceptionTranslator)
|
||||
* @see #releaseSession
|
||||
* @see HibernateTemplate
|
||||
*/
|
||||
public static Session getSession(SessionFactory sessionFactory, boolean allowCreate)
|
||||
throws DataAccessResourceFailureException, IllegalStateException {
|
||||
|
||||
try {
|
||||
return doGetSession(sessionFactory, null, null, allowCreate);
|
||||
}
|
||||
catch (HibernateException ex) {
|
||||
throw new DataAccessResourceFailureException("Could not open Hibernate Session", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Hibernate Session for the given SessionFactory. Is aware of and will
|
||||
* return any existing corresponding Session bound to the current thread, for
|
||||
* example when using {@link HibernateTransactionManager}. Will always create
|
||||
* a new Session otherwise.
|
||||
* <p>Supports setting a Session-level Hibernate entity interceptor that allows
|
||||
* to inspect and change property values before writing to and reading from the
|
||||
* database. Such an interceptor can also be set at the SessionFactory level
|
||||
* (i.e. on LocalSessionFactoryBean), on HibernateTransactionManager, etc.
|
||||
* @param sessionFactory Hibernate SessionFactory to create the session with
|
||||
* @param entityInterceptor Hibernate entity interceptor, or {@code null} if none
|
||||
* @param jdbcExceptionTranslator SQLExcepionTranslator to use for flushing the
|
||||
* Session on transaction synchronization (may be {@code null}; only used
|
||||
* when actually registering a transaction synchronization)
|
||||
* @return the Hibernate Session
|
||||
* @throws DataAccessResourceFailureException if the Session couldn't be created
|
||||
* @see LocalSessionFactoryBean#setEntityInterceptor
|
||||
* @see HibernateTemplate#setEntityInterceptor
|
||||
*/
|
||||
public static Session getSession(
|
||||
SessionFactory sessionFactory, Interceptor entityInterceptor,
|
||||
SQLExceptionTranslator jdbcExceptionTranslator) throws DataAccessResourceFailureException {
|
||||
|
||||
try {
|
||||
return doGetSession(sessionFactory, entityInterceptor, jdbcExceptionTranslator, true);
|
||||
}
|
||||
catch (HibernateException ex) {
|
||||
throw new DataAccessResourceFailureException("Could not open Hibernate Session", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Hibernate Session for the given SessionFactory. Is aware of and will
|
||||
* return any existing corresponding Session bound to the current thread, for
|
||||
* example when using {@link HibernateTransactionManager}. Will create a new
|
||||
* Session otherwise, if "allowCreate" is {@code true}.
|
||||
* <p>Throws the original HibernateException, in contrast to {@link #getSession}.
|
||||
* @param sessionFactory Hibernate SessionFactory to create the session with
|
||||
* @param allowCreate whether a non-transactional Session should be created
|
||||
* when no transactional Session can be found for the current thread
|
||||
* @return the Hibernate Session
|
||||
* @throws HibernateException if the Session couldn't be created
|
||||
* @throws IllegalStateException if no thread-bound Session found and allowCreate false
|
||||
*/
|
||||
public static Session doGetSession(SessionFactory sessionFactory, boolean allowCreate)
|
||||
throws HibernateException, IllegalStateException {
|
||||
|
||||
return doGetSession(sessionFactory, null, null, allowCreate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Hibernate Session for the given SessionFactory. Is aware of and will
|
||||
* return any existing corresponding Session bound to the current thread, for
|
||||
* example when using {@link HibernateTransactionManager}. Will create a new
|
||||
* Session otherwise, if "allowCreate" is {@code true}.
|
||||
* <p>Same as {@link #getSession}, but throwing the original HibernateException.
|
||||
* @param sessionFactory Hibernate SessionFactory to create the session with
|
||||
* @param entityInterceptor Hibernate entity interceptor, or {@code null} if none
|
||||
* @param jdbcExceptionTranslator SQLExcepionTranslator to use for flushing the
|
||||
* Session on transaction synchronization (may be {@code null})
|
||||
* @param allowCreate whether a non-transactional Session should be created
|
||||
* when no transactional Session can be found for the current thread
|
||||
* @return the Hibernate Session
|
||||
* @throws HibernateException if the Session couldn't be created
|
||||
* @throws IllegalStateException if no thread-bound Session found and
|
||||
* "allowCreate" is {@code false}
|
||||
*/
|
||||
private static Session doGetSession(
|
||||
SessionFactory sessionFactory, Interceptor entityInterceptor,
|
||||
SQLExceptionTranslator jdbcExceptionTranslator, boolean allowCreate)
|
||||
throws HibernateException, IllegalStateException {
|
||||
|
||||
Assert.notNull(sessionFactory, "No SessionFactory specified");
|
||||
|
||||
Object resource = TransactionSynchronizationManager.getResource(sessionFactory);
|
||||
if (resource instanceof Session) {
|
||||
return (Session) resource;
|
||||
}
|
||||
SessionHolder sessionHolder = (SessionHolder) resource;
|
||||
if (sessionHolder != null && !sessionHolder.isEmpty()) {
|
||||
// pre-bound Hibernate Session
|
||||
Session session = null;
|
||||
if (TransactionSynchronizationManager.isSynchronizationActive() &&
|
||||
sessionHolder.doesNotHoldNonDefaultSession()) {
|
||||
// Spring transaction management is active ->
|
||||
// register pre-bound Session with it for transactional flushing.
|
||||
session = sessionHolder.getValidatedSession();
|
||||
if (session != null && !sessionHolder.isSynchronizedWithTransaction()) {
|
||||
logger.debug("Registering Spring transaction synchronization for existing Hibernate Session");
|
||||
TransactionSynchronizationManager.registerSynchronization(
|
||||
new SpringSessionSynchronization(sessionHolder, sessionFactory, jdbcExceptionTranslator, false));
|
||||
sessionHolder.setSynchronizedWithTransaction(true);
|
||||
// Switch to FlushMode.AUTO, as we have to assume a thread-bound Session
|
||||
// with FlushMode.MANUAL, which needs to allow flushing within the transaction.
|
||||
FlushMode flushMode = session.getFlushMode();
|
||||
if (flushMode.lessThan(FlushMode.COMMIT) &&
|
||||
!TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
|
||||
session.setFlushMode(FlushMode.AUTO);
|
||||
sessionHolder.setPreviousFlushMode(flushMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// No Spring transaction management active -> try JTA transaction synchronization.
|
||||
session = getJtaSynchronizedSession(sessionHolder, sessionFactory, jdbcExceptionTranslator);
|
||||
}
|
||||
if (session != null) {
|
||||
return session;
|
||||
}
|
||||
}
|
||||
|
||||
logger.debug("Opening Hibernate Session");
|
||||
Session session = (entityInterceptor != null ?
|
||||
sessionFactory.openSession(entityInterceptor) : sessionFactory.openSession());
|
||||
|
||||
// Use same Session for further Hibernate actions within the transaction.
|
||||
// Thread object will get removed by synchronization at transaction completion.
|
||||
if (TransactionSynchronizationManager.isSynchronizationActive()) {
|
||||
// We're within a Spring-managed transaction, possibly from JtaTransactionManager.
|
||||
logger.debug("Registering Spring transaction synchronization for new Hibernate Session");
|
||||
SessionHolder holderToUse = sessionHolder;
|
||||
if (holderToUse == null) {
|
||||
holderToUse = new SessionHolder(session);
|
||||
}
|
||||
else {
|
||||
holderToUse.addSession(session);
|
||||
}
|
||||
if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
|
||||
session.setFlushMode(FlushMode.MANUAL);
|
||||
}
|
||||
TransactionSynchronizationManager.registerSynchronization(
|
||||
new SpringSessionSynchronization(holderToUse, sessionFactory, jdbcExceptionTranslator, true));
|
||||
holderToUse.setSynchronizedWithTransaction(true);
|
||||
if (holderToUse != sessionHolder) {
|
||||
TransactionSynchronizationManager.bindResource(sessionFactory, holderToUse);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// No Spring transaction management active -> try JTA transaction synchronization.
|
||||
registerJtaSynchronization(session, sessionFactory, jdbcExceptionTranslator, sessionHolder);
|
||||
}
|
||||
|
||||
// Check whether we are allowed to return the Session.
|
||||
if (!allowCreate && !isSessionTransactional(session, sessionFactory)) {
|
||||
closeSession(session);
|
||||
throw new IllegalStateException("No Hibernate Session bound to thread, " +
|
||||
"and configuration does not allow creation of non-transactional one here");
|
||||
}
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a Session from the given SessionHolder, potentially from a
|
||||
* JTA transaction synchronization.
|
||||
* @param sessionHolder the SessionHolder to check
|
||||
* @param sessionFactory the SessionFactory to get the JTA TransactionManager from
|
||||
* @param jdbcExceptionTranslator SQLExcepionTranslator to use for flushing the
|
||||
* Session on transaction synchronization (may be {@code null})
|
||||
* @return the associated Session, if any
|
||||
* @throws DataAccessResourceFailureException if the Session couldn't be created
|
||||
*/
|
||||
private static Session getJtaSynchronizedSession(
|
||||
SessionHolder sessionHolder, SessionFactory sessionFactory,
|
||||
SQLExceptionTranslator jdbcExceptionTranslator) throws DataAccessResourceFailureException {
|
||||
|
||||
// JTA synchronization is only possible with a javax.transaction.TransactionManager.
|
||||
// We'll check the Hibernate SessionFactory: If a TransactionManagerLookup is specified
|
||||
// in Hibernate configuration, it will contain a TransactionManager reference.
|
||||
TransactionManager jtaTm = getJtaTransactionManager(sessionFactory, sessionHolder.getAnySession());
|
||||
if (jtaTm != null) {
|
||||
// Check whether JTA transaction management is active ->
|
||||
// fetch pre-bound Session for the current JTA transaction, if any.
|
||||
// (just necessary for JTA transaction suspension, with an individual
|
||||
// Hibernate Session per currently active/suspended transaction)
|
||||
try {
|
||||
// Look for transaction-specific Session.
|
||||
Transaction jtaTx = jtaTm.getTransaction();
|
||||
if (jtaTx != null) {
|
||||
int jtaStatus = jtaTx.getStatus();
|
||||
if (jtaStatus == Status.STATUS_ACTIVE || jtaStatus == Status.STATUS_MARKED_ROLLBACK) {
|
||||
Session session = sessionHolder.getValidatedSession(jtaTx);
|
||||
if (session == null && !sessionHolder.isSynchronizedWithTransaction()) {
|
||||
// No transaction-specific Session found: If not already marked as
|
||||
// synchronized with transaction, register the default thread-bound
|
||||
// Session as JTA-transactional. If there is no default Session,
|
||||
// we're a new inner JTA transaction with an outer one being suspended:
|
||||
// In that case, we'll return null to trigger opening of a new Session.
|
||||
session = sessionHolder.getValidatedSession();
|
||||
if (session != null) {
|
||||
logger.debug("Registering JTA transaction synchronization for existing Hibernate Session");
|
||||
sessionHolder.addSession(jtaTx, session);
|
||||
jtaTx.registerSynchronization(
|
||||
new SpringJtaSynchronizationAdapter(
|
||||
new SpringSessionSynchronization(sessionHolder, sessionFactory, jdbcExceptionTranslator, false),
|
||||
jtaTm));
|
||||
sessionHolder.setSynchronizedWithTransaction(true);
|
||||
// Switch to FlushMode.AUTO, as we have to assume a thread-bound Session
|
||||
// with FlushMode.NEVER, which needs to allow flushing within the transaction.
|
||||
FlushMode flushMode = session.getFlushMode();
|
||||
if (flushMode.lessThan(FlushMode.COMMIT)) {
|
||||
session.setFlushMode(FlushMode.AUTO);
|
||||
sessionHolder.setPreviousFlushMode(flushMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
return session;
|
||||
}
|
||||
}
|
||||
// No transaction active -> simply return default thread-bound Session, if any
|
||||
// (possibly from OpenSessionInViewFilter/Interceptor).
|
||||
return sessionHolder.getValidatedSession();
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
throw new DataAccessResourceFailureException("Could not check JTA transaction", ex);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// No JTA TransactionManager -> simply return default thread-bound Session, if any
|
||||
// (possibly from OpenSessionInViewFilter/Interceptor).
|
||||
return sessionHolder.getValidatedSession();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a JTA synchronization for the given Session, if any.
|
||||
* @param sessionHolder the existing thread-bound SessionHolder, if any
|
||||
* @param session the Session to register
|
||||
* @param sessionFactory the SessionFactory that the Session was created with
|
||||
* @param jdbcExceptionTranslator SQLExcepionTranslator to use for flushing the
|
||||
* Session on transaction synchronization (may be {@code null})
|
||||
*/
|
||||
private static void registerJtaSynchronization(Session session, SessionFactory sessionFactory,
|
||||
SQLExceptionTranslator jdbcExceptionTranslator, SessionHolder sessionHolder) {
|
||||
|
||||
// JTA synchronization is only possible with a javax.transaction.TransactionManager.
|
||||
// We'll check the Hibernate SessionFactory: If a TransactionManagerLookup is specified
|
||||
// in Hibernate configuration, it will contain a TransactionManager reference.
|
||||
TransactionManager jtaTm = getJtaTransactionManager(sessionFactory, session);
|
||||
if (jtaTm != null) {
|
||||
try {
|
||||
Transaction jtaTx = jtaTm.getTransaction();
|
||||
if (jtaTx != null) {
|
||||
int jtaStatus = jtaTx.getStatus();
|
||||
if (jtaStatus == Status.STATUS_ACTIVE || jtaStatus == Status.STATUS_MARKED_ROLLBACK) {
|
||||
logger.debug("Registering JTA transaction synchronization for new Hibernate Session");
|
||||
SessionHolder holderToUse = sessionHolder;
|
||||
// Register JTA Transaction with existing SessionHolder.
|
||||
// Create a new SessionHolder if none existed before.
|
||||
if (holderToUse == null) {
|
||||
holderToUse = new SessionHolder(jtaTx, session);
|
||||
}
|
||||
else {
|
||||
holderToUse.addSession(jtaTx, session);
|
||||
}
|
||||
jtaTx.registerSynchronization(
|
||||
new SpringJtaSynchronizationAdapter(
|
||||
new SpringSessionSynchronization(holderToUse, sessionFactory, jdbcExceptionTranslator, true),
|
||||
jtaTm));
|
||||
holderToUse.setSynchronizedWithTransaction(true);
|
||||
if (holderToUse != sessionHolder) {
|
||||
TransactionSynchronizationManager.bindResource(sessionFactory, holderToUse);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
throw new DataAccessResourceFailureException(
|
||||
"Could not register synchronization with JTA TransactionManager", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a new Hibernate Session from the given SessionFactory.
|
||||
* Will return a new Session even if there already is a pre-bound
|
||||
* Session for the given SessionFactory.
|
||||
* <p>Within a transaction, this method will create a new Session
|
||||
* that shares the transaction's JDBC Connection. More specifically,
|
||||
* it will use the same JDBC Connection as the pre-bound Hibernate Session.
|
||||
* @param sessionFactory Hibernate SessionFactory to create the session with
|
||||
* @return the new Session
|
||||
*/
|
||||
public static Session getNewSession(SessionFactory sessionFactory) {
|
||||
return getNewSession(sessionFactory, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a new Hibernate Session from the given SessionFactory.
|
||||
* Will return a new Session even if there already is a pre-bound
|
||||
* Session for the given SessionFactory.
|
||||
* <p>Within a transaction, this method will create a new Session
|
||||
* that shares the transaction's JDBC Connection. More specifically,
|
||||
* it will use the same JDBC Connection as the pre-bound Hibernate Session.
|
||||
* @param sessionFactory Hibernate SessionFactory to create the session with
|
||||
* @param entityInterceptor Hibernate entity interceptor, or {@code null} if none
|
||||
* @return the new Session
|
||||
*/
|
||||
public static Session getNewSession(SessionFactory sessionFactory, Interceptor entityInterceptor) {
|
||||
Assert.notNull(sessionFactory, "No SessionFactory specified");
|
||||
|
||||
try {
|
||||
SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
|
||||
if (sessionHolder != null && !sessionHolder.isEmpty()) {
|
||||
if (entityInterceptor != null) {
|
||||
return sessionFactory.openSession(sessionHolder.getAnySession().connection(), entityInterceptor);
|
||||
}
|
||||
else {
|
||||
return sessionFactory.openSession(sessionHolder.getAnySession().connection());
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (entityInterceptor != null) {
|
||||
return sessionFactory.openSession(entityInterceptor);
|
||||
}
|
||||
else {
|
||||
return sessionFactory.openSession();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (HibernateException ex) {
|
||||
throw new DataAccessResourceFailureException("Could not open Hibernate Session", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Stringify the given Session for debug logging.
|
||||
* Returns output equivalent to {@code Object.toString()}:
|
||||
* the fully qualified class name + "@" + the identity hash code.
|
||||
* <p>The sole reason why this is necessary is because Hibernate3's
|
||||
* {@code Session.toString()} implementation is broken (and won't be fixed):
|
||||
* it logs the toString representation of all persistent objects in the Session,
|
||||
* which might lead to ConcurrentModificationExceptions if the persistent objects
|
||||
* in turn refer to the Session (for example, for lazy loading).
|
||||
* @param session the Hibernate Session to stringify
|
||||
* @return the String representation of the given Session
|
||||
*/
|
||||
public static String toString(Session session) {
|
||||
return session.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(session));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether there is a transactional Hibernate Session for the current thread,
|
||||
* that is, a Session bound to the current thread by Spring's transaction facilities.
|
||||
* @param sessionFactory Hibernate SessionFactory to check (may be {@code null})
|
||||
* @return whether there is a transactional Session for current thread
|
||||
*/
|
||||
public static boolean hasTransactionalSession(SessionFactory sessionFactory) {
|
||||
if (sessionFactory == null) {
|
||||
return false;
|
||||
}
|
||||
SessionHolder sessionHolder =
|
||||
(SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
|
||||
return (sessionHolder != null && !sessionHolder.isEmpty());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the given Hibernate Session is transactional, that is,
|
||||
* bound to the current thread by Spring's transaction facilities.
|
||||
* @param session the Hibernate Session to check
|
||||
* @param sessionFactory Hibernate SessionFactory that the Session was created with
|
||||
* (may be {@code null})
|
||||
* @return whether the Session is transactional
|
||||
*/
|
||||
public static boolean isSessionTransactional(Session session, SessionFactory sessionFactory) {
|
||||
if (sessionFactory == null) {
|
||||
return false;
|
||||
}
|
||||
SessionHolder sessionHolder =
|
||||
(SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
|
||||
return (sessionHolder != null && sessionHolder.containsSession(session));
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the current transaction timeout, if any, to the given
|
||||
* Hibernate Query object.
|
||||
* @param query the Hibernate Query object
|
||||
* @param sessionFactory Hibernate SessionFactory that the Query was created for
|
||||
* (may be {@code null})
|
||||
* @see org.hibernate.Query#setTimeout
|
||||
*/
|
||||
public static void applyTransactionTimeout(Query query, SessionFactory sessionFactory) {
|
||||
Assert.notNull(query, "No Query object specified");
|
||||
if (sessionFactory != null) {
|
||||
SessionHolder sessionHolder =
|
||||
(SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
|
||||
if (sessionHolder != null && sessionHolder.hasTimeout()) {
|
||||
query.setTimeout(sessionHolder.getTimeToLiveInSeconds());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the current transaction timeout, if any, to the given
|
||||
* Hibernate Criteria object.
|
||||
* @param criteria the Hibernate Criteria object
|
||||
* @param sessionFactory Hibernate SessionFactory that the Criteria was created for
|
||||
* @see org.hibernate.Criteria#setTimeout
|
||||
*/
|
||||
public static void applyTransactionTimeout(Criteria criteria, SessionFactory sessionFactory) {
|
||||
Assert.notNull(criteria, "No Criteria object specified");
|
||||
if (sessionFactory != null) {
|
||||
SessionHolder sessionHolder =
|
||||
(SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
|
||||
if (sessionHolder != null && sessionHolder.hasTimeout()) {
|
||||
criteria.setTimeout(sessionHolder.getTimeToLiveInSeconds());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given HibernateException to an appropriate exception
|
||||
* from the {@code org.springframework.dao} hierarchy.
|
||||
* @param ex HibernateException that occurred
|
||||
* @return the corresponding DataAccessException instance
|
||||
* @see HibernateAccessor#convertHibernateAccessException
|
||||
* @see HibernateTransactionManager#convertHibernateAccessException
|
||||
*/
|
||||
public static DataAccessException convertHibernateAccessException(HibernateException ex) {
|
||||
if (ex instanceof JDBCConnectionException) {
|
||||
return new DataAccessResourceFailureException(ex.getMessage(), ex);
|
||||
}
|
||||
if (ex instanceof SQLGrammarException) {
|
||||
SQLGrammarException jdbcEx = (SQLGrammarException) ex;
|
||||
return new InvalidDataAccessResourceUsageException(ex.getMessage() + "; SQL [" + jdbcEx.getSQL() + "]", ex);
|
||||
}
|
||||
if (ex instanceof QueryTimeoutException) {
|
||||
QueryTimeoutException jdbcEx = (QueryTimeoutException) ex;
|
||||
return new org.springframework.dao.QueryTimeoutException(ex.getMessage() + "; SQL [" + jdbcEx.getSQL() + "]", ex);
|
||||
}
|
||||
if (ex instanceof LockAcquisitionException) {
|
||||
LockAcquisitionException jdbcEx = (LockAcquisitionException) ex;
|
||||
return new CannotAcquireLockException(ex.getMessage() + "; SQL [" + jdbcEx.getSQL() + "]", ex);
|
||||
}
|
||||
if (ex instanceof PessimisticLockException) {
|
||||
PessimisticLockException jdbcEx = (PessimisticLockException) ex;
|
||||
return new PessimisticLockingFailureException(ex.getMessage() + "; SQL [" + jdbcEx.getSQL() + "]", ex);
|
||||
}
|
||||
if (ex instanceof ConstraintViolationException) {
|
||||
ConstraintViolationException jdbcEx = (ConstraintViolationException) ex;
|
||||
return new DataIntegrityViolationException(ex.getMessage() + "; SQL [" + jdbcEx.getSQL() +
|
||||
"]; constraint [" + jdbcEx.getConstraintName() + "]", ex);
|
||||
}
|
||||
if (ex instanceof DataException) {
|
||||
DataException jdbcEx = (DataException) ex;
|
||||
return new DataIntegrityViolationException(ex.getMessage() + "; SQL [" + jdbcEx.getSQL() + "]", ex);
|
||||
}
|
||||
if (ex instanceof JDBCException) {
|
||||
return new HibernateJdbcException((JDBCException) ex);
|
||||
}
|
||||
// end of JDBCException (subclass) handling
|
||||
|
||||
if (ex instanceof QueryException) {
|
||||
return new HibernateQueryException((QueryException) ex);
|
||||
}
|
||||
if (ex instanceof NonUniqueResultException) {
|
||||
return new IncorrectResultSizeDataAccessException(ex.getMessage(), 1, ex);
|
||||
}
|
||||
if (ex instanceof NonUniqueObjectException) {
|
||||
return new DuplicateKeyException(ex.getMessage(), ex);
|
||||
}
|
||||
if (ex instanceof PropertyValueException) {
|
||||
return new DataIntegrityViolationException(ex.getMessage(), ex);
|
||||
}
|
||||
if (ex instanceof PersistentObjectException) {
|
||||
return new InvalidDataAccessApiUsageException(ex.getMessage(), ex);
|
||||
}
|
||||
if (ex instanceof TransientObjectException) {
|
||||
return new InvalidDataAccessApiUsageException(ex.getMessage(), ex);
|
||||
}
|
||||
if (ex instanceof ObjectDeletedException) {
|
||||
return new InvalidDataAccessApiUsageException(ex.getMessage(), ex);
|
||||
}
|
||||
if (ex instanceof UnresolvableObjectException) {
|
||||
return new HibernateObjectRetrievalFailureException((UnresolvableObjectException) ex);
|
||||
}
|
||||
if (ex instanceof WrongClassException) {
|
||||
return new HibernateObjectRetrievalFailureException((WrongClassException) ex);
|
||||
}
|
||||
if (ex instanceof StaleObjectStateException) {
|
||||
return new HibernateOptimisticLockingFailureException((StaleObjectStateException) ex);
|
||||
}
|
||||
if (ex instanceof StaleStateException) {
|
||||
return new HibernateOptimisticLockingFailureException((StaleStateException) ex);
|
||||
}
|
||||
if (ex instanceof OptimisticLockException) {
|
||||
return new HibernateOptimisticLockingFailureException((OptimisticLockException) ex);
|
||||
}
|
||||
|
||||
// fallback
|
||||
return new HibernateSystemException(ex);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine whether deferred close is active for the current thread
|
||||
* and the given SessionFactory.
|
||||
* @param sessionFactory the Hibernate SessionFactory to check
|
||||
* @return whether deferred close is active
|
||||
*/
|
||||
public static boolean isDeferredCloseActive(SessionFactory sessionFactory) {
|
||||
Assert.notNull(sessionFactory, "No SessionFactory specified");
|
||||
Map<SessionFactory, Set<Session>> holderMap = deferredCloseHolder.get();
|
||||
return (holderMap != null && holderMap.containsKey(sessionFactory));
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize deferred close for the current thread and the given SessionFactory.
|
||||
* Sessions will not be actually closed on close calls then, but rather at a
|
||||
* {@link #processDeferredClose} call at a finishing point (like request completion).
|
||||
* <p>Used by {@link org.springframework.orm.hibernate3.support.OpenSessionInViewFilter}
|
||||
* and {@link org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor}
|
||||
* when not configured for a single session.
|
||||
* @param sessionFactory the Hibernate SessionFactory to initialize deferred close for
|
||||
* @see #processDeferredClose
|
||||
* @see #releaseSession
|
||||
* @see org.springframework.orm.hibernate3.support.OpenSessionInViewFilter#setSingleSession
|
||||
* @see org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor#setSingleSession
|
||||
*/
|
||||
public static void initDeferredClose(SessionFactory sessionFactory) {
|
||||
Assert.notNull(sessionFactory, "No SessionFactory specified");
|
||||
logger.debug("Initializing deferred close of Hibernate Sessions");
|
||||
Map<SessionFactory, Set<Session>> holderMap = deferredCloseHolder.get();
|
||||
if (holderMap == null) {
|
||||
holderMap = new HashMap<SessionFactory, Set<Session>>();
|
||||
deferredCloseHolder.set(holderMap);
|
||||
}
|
||||
holderMap.put(sessionFactory, new LinkedHashSet<Session>(4));
|
||||
}
|
||||
|
||||
/**
|
||||
* Process all Hibernate Sessions that have been registered for deferred close
|
||||
* for the given SessionFactory.
|
||||
* @param sessionFactory the Hibernate SessionFactory to process deferred close for
|
||||
* @see #initDeferredClose
|
||||
* @see #releaseSession
|
||||
*/
|
||||
public static void processDeferredClose(SessionFactory sessionFactory) {
|
||||
Assert.notNull(sessionFactory, "No SessionFactory specified");
|
||||
Map<SessionFactory, Set<Session>> holderMap = deferredCloseHolder.get();
|
||||
if (holderMap == null || !holderMap.containsKey(sessionFactory)) {
|
||||
throw new IllegalStateException("Deferred close not active for SessionFactory [" + sessionFactory + "]");
|
||||
}
|
||||
logger.debug("Processing deferred close of Hibernate Sessions");
|
||||
Set<Session> sessions = holderMap.remove(sessionFactory);
|
||||
for (Session session : sessions) {
|
||||
closeSession(session);
|
||||
}
|
||||
if (holderMap.isEmpty()) {
|
||||
deferredCloseHolder.remove();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the given Session, created via the given factory,
|
||||
* if it is not managed externally (i.e. not bound to the thread).
|
||||
* @param session the Hibernate Session to close (may be {@code null})
|
||||
* @param sessionFactory Hibernate SessionFactory that the Session was created with
|
||||
* (may be {@code null})
|
||||
*/
|
||||
public static void releaseSession(Session session, SessionFactory sessionFactory) {
|
||||
if (session == null) {
|
||||
return;
|
||||
}
|
||||
// Only close non-transactional Sessions.
|
||||
if (!isSessionTransactional(session, sessionFactory)) {
|
||||
closeSessionOrRegisterDeferredClose(session, sessionFactory);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the given Session or register it for deferred close.
|
||||
* @param session the Hibernate Session to close
|
||||
* @param sessionFactory Hibernate SessionFactory that the Session was created with
|
||||
* (may be {@code null})
|
||||
* @see #initDeferredClose
|
||||
* @see #processDeferredClose
|
||||
*/
|
||||
static void closeSessionOrRegisterDeferredClose(Session session, SessionFactory sessionFactory) {
|
||||
Map<SessionFactory, Set<Session>> holderMap = deferredCloseHolder.get();
|
||||
if (holderMap != null && sessionFactory != null && holderMap.containsKey(sessionFactory)) {
|
||||
logger.debug("Registering Hibernate Session for deferred close");
|
||||
// Switch Session to FlushMode.MANUAL for remaining lifetime.
|
||||
session.setFlushMode(FlushMode.MANUAL);
|
||||
Set<Session> sessions = holderMap.get(sessionFactory);
|
||||
sessions.add(session);
|
||||
}
|
||||
else {
|
||||
closeSession(session);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform actual closing of the Hibernate Session,
|
||||
* catching and logging any cleanup exceptions thrown.
|
||||
* @param session the Hibernate Session to close (may be {@code null})
|
||||
* @see org.hibernate.Session#close()
|
||||
*/
|
||||
public static void closeSession(Session session) {
|
||||
if (session != null) {
|
||||
logger.debug("Closing Hibernate Session");
|
||||
try {
|
||||
session.close();
|
||||
}
|
||||
catch (HibernateException ex) {
|
||||
logger.debug("Could not close Hibernate Session", ex);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
logger.debug("Unexpected exception on closing Hibernate Session", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,151 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate3;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.hibernate.FlushMode;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.Transaction;
|
||||
|
||||
import org.springframework.transaction.support.ResourceHolderSupport;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Session holder, wrapping a Hibernate Session and a Hibernate Transaction.
|
||||
* HibernateTransactionManager binds instances of this class to the thread,
|
||||
* for a given SessionFactory.
|
||||
*
|
||||
* <p>Note: This is an SPI class, not intended to be used by applications.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @see HibernateTransactionManager
|
||||
* @see SessionFactoryUtils
|
||||
* @deprecated as of Spring 4.3, in favor of Hibernate 4.x/5.x
|
||||
*/
|
||||
@Deprecated
|
||||
public class SessionHolder extends ResourceHolderSupport {
|
||||
|
||||
private static final Object DEFAULT_KEY = new Object();
|
||||
|
||||
/**
|
||||
* This Map needs to be concurrent because there might be multi-threaded
|
||||
* access in the case of JTA with remote transaction propagation.
|
||||
*/
|
||||
private final Map<Object, Session> sessionMap = new ConcurrentHashMap<Object, Session>(1);
|
||||
|
||||
private Transaction transaction;
|
||||
|
||||
private FlushMode previousFlushMode;
|
||||
|
||||
|
||||
public SessionHolder(Session session) {
|
||||
addSession(session);
|
||||
}
|
||||
|
||||
public SessionHolder(Object key, Session session) {
|
||||
addSession(key, session);
|
||||
}
|
||||
|
||||
|
||||
public Session getSession() {
|
||||
return getSession(DEFAULT_KEY);
|
||||
}
|
||||
|
||||
public Session getSession(Object key) {
|
||||
return this.sessionMap.get(key);
|
||||
}
|
||||
|
||||
public Session getValidatedSession() {
|
||||
return getValidatedSession(DEFAULT_KEY);
|
||||
}
|
||||
|
||||
public Session getValidatedSession(Object key) {
|
||||
Session session = this.sessionMap.get(key);
|
||||
// Check for dangling Session that's around but already closed.
|
||||
// Effectively an assertion: that should never happen in practice.
|
||||
// We'll seamlessly remove the Session here, to not let it cause
|
||||
// any side effects.
|
||||
if (session != null && !session.isOpen()) {
|
||||
this.sessionMap.remove(key);
|
||||
session = null;
|
||||
}
|
||||
return session;
|
||||
}
|
||||
|
||||
public Session getAnySession() {
|
||||
if (!this.sessionMap.isEmpty()) {
|
||||
return this.sessionMap.values().iterator().next();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void addSession(Session session) {
|
||||
addSession(DEFAULT_KEY, session);
|
||||
}
|
||||
|
||||
public void addSession(Object key, Session session) {
|
||||
Assert.notNull(key, "Key must not be null");
|
||||
Assert.notNull(session, "Session must not be null");
|
||||
this.sessionMap.put(key, session);
|
||||
}
|
||||
|
||||
public Session removeSession(Object key) {
|
||||
return this.sessionMap.remove(key);
|
||||
}
|
||||
|
||||
public boolean containsSession(Session session) {
|
||||
return this.sessionMap.containsValue(session);
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return this.sessionMap.isEmpty();
|
||||
}
|
||||
|
||||
public boolean doesNotHoldNonDefaultSession() {
|
||||
return this.sessionMap.isEmpty() ||
|
||||
(this.sessionMap.size() == 1 && this.sessionMap.containsKey(DEFAULT_KEY));
|
||||
}
|
||||
|
||||
|
||||
public void setTransaction(Transaction transaction) {
|
||||
this.transaction = transaction;
|
||||
}
|
||||
|
||||
public Transaction getTransaction() {
|
||||
return this.transaction;
|
||||
}
|
||||
|
||||
public void setPreviousFlushMode(FlushMode previousFlushMode) {
|
||||
this.previousFlushMode = previousFlushMode;
|
||||
}
|
||||
|
||||
public FlushMode getPreviousFlushMode() {
|
||||
return this.previousFlushMode;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
super.clear();
|
||||
this.transaction = null;
|
||||
this.previousFlushMode = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate3;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.classic.Session;
|
||||
import org.hibernate.context.CurrentSessionContext;
|
||||
import org.hibernate.engine.SessionFactoryImplementor;
|
||||
|
||||
/**
|
||||
* Implementation of Hibernate 3.1's CurrentSessionContext interface
|
||||
* that delegates to Spring's SessionFactoryUtils for providing a
|
||||
* Spring-managed current Session.
|
||||
*
|
||||
* <p>Used by Spring's {@link LocalSessionFactoryBean} when told to expose a
|
||||
* transaction-aware SessionFactory. This is the default as of Spring 2.5.
|
||||
*
|
||||
* <p>This CurrentSessionContext implementation can also be specified in custom
|
||||
* SessionFactory setup through the "hibernate.current_session_context_class"
|
||||
* property, with the fully qualified name of this class as value.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
* @see SessionFactoryUtils#doGetSession
|
||||
* @see LocalSessionFactoryBean#setExposeTransactionAwareSessionFactory
|
||||
* @deprecated as of Spring 4.3, in favor of Hibernate 4.x/5.x
|
||||
*/
|
||||
@Deprecated
|
||||
@SuppressWarnings("serial")
|
||||
public class SpringSessionContext implements CurrentSessionContext {
|
||||
|
||||
private final SessionFactoryImplementor sessionFactory;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new SpringSessionContext for the given Hibernate SessionFactory.
|
||||
* @param sessionFactory the SessionFactory to provide current Sessions for
|
||||
*/
|
||||
public SpringSessionContext(SessionFactoryImplementor sessionFactory) {
|
||||
this.sessionFactory = sessionFactory;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve the Spring-managed Session for the current thread, if any.
|
||||
*/
|
||||
@Override
|
||||
public Session currentSession() throws HibernateException {
|
||||
try {
|
||||
return (org.hibernate.classic.Session) SessionFactoryUtils.doGetSession(this.sessionFactory, false);
|
||||
}
|
||||
catch (IllegalStateException ex) {
|
||||
throw new HibernateException(ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,268 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate3;
|
||||
|
||||
import javax.transaction.SystemException;
|
||||
import javax.transaction.Transaction;
|
||||
import javax.transaction.TransactionManager;
|
||||
|
||||
import org.hibernate.FlushMode;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.JDBCException;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.engine.SessionImplementor;
|
||||
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.DataAccessResourceFailureException;
|
||||
import org.springframework.jdbc.support.SQLExceptionTranslator;
|
||||
import org.springframework.transaction.support.TransactionSynchronization;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
|
||||
/**
|
||||
* Callback for resource cleanup at the end of a Spring-managed JTA transaction,
|
||||
* that is, when participating in a JtaTransactionManager transaction.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @see SessionFactoryUtils
|
||||
* @see org.springframework.transaction.jta.JtaTransactionManager
|
||||
* @deprecated as of Spring 4.3, in favor of Hibernate 4.x/5.x
|
||||
*/
|
||||
@Deprecated
|
||||
class SpringSessionSynchronization implements TransactionSynchronization, Ordered {
|
||||
|
||||
private final SessionHolder sessionHolder;
|
||||
|
||||
private final SessionFactory sessionFactory;
|
||||
|
||||
private final SQLExceptionTranslator jdbcExceptionTranslator;
|
||||
|
||||
private final boolean newSession;
|
||||
|
||||
/**
|
||||
* Whether Hibernate has a looked-up JTA TransactionManager that it will
|
||||
* automatically register CacheSynchronizations with on Session connect.
|
||||
*/
|
||||
private boolean hibernateTransactionCompletion = false;
|
||||
|
||||
private Transaction jtaTransaction;
|
||||
|
||||
private boolean holderActive = true;
|
||||
|
||||
|
||||
public SpringSessionSynchronization(
|
||||
SessionHolder sessionHolder, SessionFactory sessionFactory,
|
||||
SQLExceptionTranslator jdbcExceptionTranslator, boolean newSession) {
|
||||
|
||||
this.sessionHolder = sessionHolder;
|
||||
this.sessionFactory = sessionFactory;
|
||||
this.jdbcExceptionTranslator = jdbcExceptionTranslator;
|
||||
this.newSession = newSession;
|
||||
|
||||
// Check whether the SessionFactory has a JTA TransactionManager.
|
||||
TransactionManager jtaTm =
|
||||
SessionFactoryUtils.getJtaTransactionManager(sessionFactory, sessionHolder.getAnySession());
|
||||
if (jtaTm != null) {
|
||||
this.hibernateTransactionCompletion = true;
|
||||
// Fetch current JTA Transaction object
|
||||
// (just necessary for JTA transaction suspension, with an individual
|
||||
// Hibernate Session per currently active/suspended transaction).
|
||||
try {
|
||||
this.jtaTransaction = jtaTm.getTransaction();
|
||||
}
|
||||
catch (SystemException ex) {
|
||||
throw new DataAccessResourceFailureException("Could not access JTA transaction", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether there is a Hibernate Session for the current JTA
|
||||
* transaction. Else, fall back to the default thread-bound Session.
|
||||
*/
|
||||
private Session getCurrentSession() {
|
||||
Session session = null;
|
||||
if (this.jtaTransaction != null) {
|
||||
session = this.sessionHolder.getSession(this.jtaTransaction);
|
||||
}
|
||||
if (session == null) {
|
||||
session = this.sessionHolder.getSession();
|
||||
}
|
||||
return session;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return SessionFactoryUtils.SESSION_SYNCHRONIZATION_ORDER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suspend() {
|
||||
if (this.holderActive) {
|
||||
TransactionSynchronizationManager.unbindResource(this.sessionFactory);
|
||||
// Eagerly disconnect the Session here, to make release mode "on_close" work on JBoss.
|
||||
getCurrentSession().disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resume() {
|
||||
if (this.holderActive) {
|
||||
TransactionSynchronizationManager.bindResource(this.sessionFactory, this.sessionHolder);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() {
|
||||
try {
|
||||
SessionFactoryUtils.logger.debug("Flushing Hibernate Session on explicit request");
|
||||
getCurrentSession().flush();
|
||||
}
|
||||
catch (HibernateException ex) {
|
||||
throw translateException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeCommit(boolean readOnly) throws DataAccessException {
|
||||
if (!readOnly) {
|
||||
Session session = getCurrentSession();
|
||||
// Read-write transaction -> flush the Hibernate Session.
|
||||
// Further check: only flush when not FlushMode.NEVER/MANUAL.
|
||||
if (!session.getFlushMode().lessThan(FlushMode.COMMIT)) {
|
||||
try {
|
||||
SessionFactoryUtils.logger.debug("Flushing Hibernate Session on transaction synchronization");
|
||||
session.flush();
|
||||
}
|
||||
catch (HibernateException ex) {
|
||||
throw translateException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private DataAccessException translateException(HibernateException ex) {
|
||||
if (this.jdbcExceptionTranslator != null && ex instanceof JDBCException) {
|
||||
JDBCException jdbcEx = (JDBCException) ex;
|
||||
return this.jdbcExceptionTranslator.translate(
|
||||
"Hibernate flushing: " + jdbcEx.getMessage(), jdbcEx.getSQL(), jdbcEx.getSQLException());
|
||||
}
|
||||
return SessionFactoryUtils.convertHibernateAccessException(ex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeCompletion() {
|
||||
if (this.jtaTransaction != null) {
|
||||
// Typically in case of a suspended JTA transaction:
|
||||
// Remove the Session for the current JTA transaction, but keep the holder.
|
||||
Session session = this.sessionHolder.removeSession(this.jtaTransaction);
|
||||
if (session != null) {
|
||||
if (this.sessionHolder.isEmpty()) {
|
||||
// No Sessions for JTA transactions bound anymore -> could remove it.
|
||||
TransactionSynchronizationManager.unbindResourceIfPossible(this.sessionFactory);
|
||||
this.holderActive = false;
|
||||
}
|
||||
// Do not close a pre-bound Session. In that case, we'll find the
|
||||
// transaction-specific Session the same as the default Session.
|
||||
if (session != this.sessionHolder.getSession()) {
|
||||
SessionFactoryUtils.closeSessionOrRegisterDeferredClose(session, this.sessionFactory);
|
||||
}
|
||||
else {
|
||||
if (this.sessionHolder.getPreviousFlushMode() != null) {
|
||||
// In case of pre-bound Session, restore previous flush mode.
|
||||
session.setFlushMode(this.sessionHolder.getPreviousFlushMode());
|
||||
}
|
||||
// Eagerly disconnect the Session here, to make release mode "on_close" work nicely.
|
||||
session.disconnect();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
// We'll only get here if there was no specific JTA transaction to handle.
|
||||
if (this.newSession) {
|
||||
// Default behavior: unbind and close the thread-bound Hibernate Session.
|
||||
TransactionSynchronizationManager.unbindResource(this.sessionFactory);
|
||||
this.holderActive = false;
|
||||
if (this.hibernateTransactionCompletion) {
|
||||
// Close the Hibernate Session here in case of a Hibernate TransactionManagerLookup:
|
||||
// Hibernate will automatically defer the actual closing until JTA transaction completion.
|
||||
// Else, the Session will be closed in the afterCompletion method, to provide the
|
||||
// correct transaction status for releasing the Session's cache locks.
|
||||
SessionFactoryUtils.closeSessionOrRegisterDeferredClose(this.sessionHolder.getSession(), this.sessionFactory);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Session session = this.sessionHolder.getSession();
|
||||
if (this.sessionHolder.getPreviousFlushMode() != null) {
|
||||
// In case of pre-bound Session, restore previous flush mode.
|
||||
session.setFlushMode(this.sessionHolder.getPreviousFlushMode());
|
||||
}
|
||||
if (this.hibernateTransactionCompletion) {
|
||||
// Eagerly disconnect the Session here, to make release mode "on_close" work nicely.
|
||||
// We know that this is appropriate if a TransactionManagerLookup has been specified.
|
||||
session.disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterCommit() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterCompletion(int status) {
|
||||
try {
|
||||
if (!this.hibernateTransactionCompletion || !this.newSession) {
|
||||
// No Hibernate TransactionManagerLookup: apply afterTransactionCompletion callback.
|
||||
// Always perform explicit afterTransactionCompletion callback for pre-bound Session,
|
||||
// even with Hibernate TransactionManagerLookup (which only applies to new Sessions).
|
||||
Session session = this.sessionHolder.getSession();
|
||||
// Provide correct transaction status for releasing the Session's cache locks,
|
||||
// if possible. Else, closing will release all cache locks assuming a rollback.
|
||||
try {
|
||||
if (session instanceof SessionImplementor) {
|
||||
((SessionImplementor) session).afterTransactionCompletion(status == STATUS_COMMITTED, null);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
// Close the Hibernate Session here if necessary
|
||||
// (closed in beforeCompletion in case of TransactionManagerLookup).
|
||||
if (this.newSession) {
|
||||
SessionFactoryUtils.closeSessionOrRegisterDeferredClose(session, this.sessionFactory);
|
||||
}
|
||||
else if (!this.hibernateTransactionCompletion) {
|
||||
session.disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!this.newSession && status != STATUS_COMMITTED) {
|
||||
// Clear all pending inserts/updates/deletes in the Session.
|
||||
// Necessary for pre-bound Sessions, to avoid inconsistent state.
|
||||
this.sessionHolder.getSession().clear();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (this.sessionHolder.doesNotHoldNonDefaultSession()) {
|
||||
this.sessionHolder.setSynchronizedWithTransaction(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,83 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate3;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.hibernate.ConnectionReleaseMode;
|
||||
import org.hibernate.Transaction;
|
||||
import org.hibernate.jdbc.JDBCContext;
|
||||
import org.hibernate.transaction.JDBCTransaction;
|
||||
import org.hibernate.transaction.TransactionFactory;
|
||||
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
|
||||
/**
|
||||
* Spring-aware implementation of the Hibernate TransactionFactory interface, aware of
|
||||
* Spring-synchronized transactions (in particular Spring-managed JTA transactions)
|
||||
* and asking for default release mode ON_CLOSE. Otherwise identical to Hibernate's
|
||||
* default {@link org.hibernate.transaction.JDBCTransactionFactory} implementation.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.5.4
|
||||
* @see org.springframework.transaction.support.TransactionSynchronizationManager
|
||||
* @see org.hibernate.transaction.JDBCTransactionFactory
|
||||
* @deprecated as of Spring 4.3, in favor of Hibernate 4.x/5.x
|
||||
*/
|
||||
@Deprecated
|
||||
public class SpringTransactionFactory implements TransactionFactory {
|
||||
|
||||
/**
|
||||
* Sets connection release mode "on_close" as default.
|
||||
* <p>This was the case for Hibernate 3.0; Hibernate 3.1 changed
|
||||
* it to "auto" (i.e. "after_statement" or "after_transaction").
|
||||
* However, for Spring's resource management (in particular for
|
||||
* HibernateTransactionManager), "on_close" is the better default.
|
||||
*/
|
||||
@Override
|
||||
public ConnectionReleaseMode getDefaultReleaseMode() {
|
||||
return ConnectionReleaseMode.ON_CLOSE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Transaction createTransaction(JDBCContext jdbcContext, Context transactionContext) {
|
||||
return new JDBCTransaction(jdbcContext, transactionContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(Properties props) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTransactionManagerRequired() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areCallbacksLocalToHibernateTransactions() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTransactionInProgress(
|
||||
JDBCContext jdbcContext, Context transactionContext, Transaction transaction) {
|
||||
|
||||
return (transaction != null && transaction.isActive()) ||
|
||||
TransactionSynchronizationManager.isActualTransactionActive();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate3;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy;
|
||||
|
||||
/**
|
||||
* Subclass of LocalDataSourceConnectionProvider that returns a
|
||||
* transaction-aware proxy for the exposed DataSource. Used if
|
||||
* LocalSessionFactoryBean's "useTransactionAwareDataSource" flag is on.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @see LocalSessionFactoryBean#setUseTransactionAwareDataSource
|
||||
* @deprecated as of Spring 4.3, in favor of Hibernate 4.x/5.x
|
||||
*/
|
||||
@Deprecated
|
||||
public class TransactionAwareDataSourceConnectionProvider extends LocalDataSourceConnectionProvider {
|
||||
|
||||
/**
|
||||
* Return a TransactionAwareDataSourceProxy for the given DataSource,
|
||||
* provided that it isn't a TransactionAwareDataSourceProxy already.
|
||||
*/
|
||||
@Override
|
||||
protected DataSource getDataSourceToUse(DataSource originalDataSource) {
|
||||
if (originalDataSource instanceof TransactionAwareDataSourceProxy) {
|
||||
return originalDataSource;
|
||||
}
|
||||
return new TransactionAwareDataSourceProxy(originalDataSource);
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation returns {@code true}: We can guarantee
|
||||
* to receive the same Connection within a transaction, as we are
|
||||
* exposing a TransactionAwareDataSourceProxy.
|
||||
*/
|
||||
@Override
|
||||
public boolean supportsAggressiveRelease() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,133 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate3;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
/**
|
||||
* Bean that encapsulates a Hibernate type definition.
|
||||
*
|
||||
* <p>Typically defined as inner bean within a LocalSessionFactoryBean
|
||||
* definition, as list element for the "typeDefinitions" bean property.
|
||||
* For example:
|
||||
*
|
||||
* <pre class="code">
|
||||
* <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
|
||||
* ...
|
||||
* <property name="typeDefinitions">
|
||||
* <list>
|
||||
* <bean class="org.springframework.orm.hibernate3.TypeDefinitionBean">
|
||||
* <property name="typeName" value="myType"/>
|
||||
* <property name="typeClass" value="mypackage.MyTypeClass"/>
|
||||
* </bean>
|
||||
* </list>
|
||||
* </property>
|
||||
* ...
|
||||
* </bean></pre>
|
||||
*
|
||||
* Alternatively, specify a bean id (or name) attribute for the inner bean,
|
||||
* instead of the "typeName" property.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @see LocalSessionFactoryBean#setTypeDefinitions(TypeDefinitionBean[])
|
||||
* @deprecated as of Spring 4.3, in favor of Hibernate 4.x/5.x
|
||||
*/
|
||||
@Deprecated
|
||||
public class TypeDefinitionBean implements BeanNameAware, InitializingBean {
|
||||
|
||||
private String typeName;
|
||||
|
||||
private String typeClass;
|
||||
|
||||
private Properties parameters = new Properties();
|
||||
|
||||
|
||||
/**
|
||||
* Set the name of the type.
|
||||
* @see org.hibernate.cfg.Mappings#addTypeDef(String, String, java.util.Properties)
|
||||
*/
|
||||
public void setTypeName(String typeName) {
|
||||
this.typeName = typeName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the type.
|
||||
*/
|
||||
public String getTypeName() {
|
||||
return typeName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the type implementation class.
|
||||
* @see org.hibernate.cfg.Mappings#addTypeDef(String, String, java.util.Properties)
|
||||
*/
|
||||
public void setTypeClass(String typeClass) {
|
||||
this.typeClass = typeClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the type implementation class.
|
||||
*/
|
||||
public String getTypeClass() {
|
||||
return typeClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify default parameters for the type.
|
||||
* This only applies to parameterized types.
|
||||
* @see org.hibernate.cfg.Mappings#addTypeDef(String, String, java.util.Properties)
|
||||
* @see org.hibernate.usertype.ParameterizedType
|
||||
*/
|
||||
public void setParameters(Properties parameters) {
|
||||
this.parameters = parameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the default parameters for the type.
|
||||
*/
|
||||
public Properties getParameters() {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* If no explicit type name has been specified, the bean name of
|
||||
* the TypeDefinitionBean will be used.
|
||||
* @see #setTypeName
|
||||
*/
|
||||
@Override
|
||||
public void setBeanName(String name) {
|
||||
if (this.typeName == null) {
|
||||
this.typeName = name;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
if (this.typeName == null) {
|
||||
throw new IllegalArgumentException("typeName is required");
|
||||
}
|
||||
if (this.typeClass == null) {
|
||||
throw new IllegalArgumentException("typeClass is required");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,228 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate3.annotation;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
|
||||
import org.springframework.context.ResourceLoaderAware;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
||||
import org.springframework.core.io.support.ResourcePatternResolver;
|
||||
import org.springframework.core.io.support.ResourcePatternUtils;
|
||||
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
|
||||
import org.springframework.core.type.classreading.MetadataReader;
|
||||
import org.springframework.core.type.classreading.MetadataReaderFactory;
|
||||
import org.springframework.core.type.filter.AnnotationTypeFilter;
|
||||
import org.springframework.core.type.filter.TypeFilter;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Subclass of Spring's standard LocalSessionFactoryBean for Hibernate,
|
||||
* supporting annotation metadata for mappings.
|
||||
*
|
||||
* <p>Example for an AnnotationSessionFactoryBean bean definition:
|
||||
*
|
||||
* <pre class="code">
|
||||
* <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
|
||||
* <property name="dataSource" ref="dataSource"/>
|
||||
* <property name="annotatedClasses">
|
||||
* <list>
|
||||
* <value>test.package.Foo</value>
|
||||
* <value>test.package.Bar</value>
|
||||
* </list>
|
||||
* </property>
|
||||
* </bean></pre>
|
||||
*
|
||||
* Or when using classpath scanning for autodetection of entity classes:
|
||||
*
|
||||
* <pre class="code">
|
||||
* <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
|
||||
* <property name="dataSource" ref="dataSource"/>
|
||||
* <property name="packagesToScan" value="test.package"/>
|
||||
* </bean></pre>
|
||||
*
|
||||
* <p>Requires Hibernate 3.6.x, as of Spring 4.0.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2.2
|
||||
* @see #setDataSource
|
||||
* @see #setHibernateProperties
|
||||
* @see #setAnnotatedClasses
|
||||
* @see #setAnnotatedPackages
|
||||
* @deprecated as of Spring 4.3, in favor of Hibernate 4.x/5.x
|
||||
*/
|
||||
@Deprecated
|
||||
public class AnnotationSessionFactoryBean extends org.springframework.orm.hibernate3.LocalSessionFactoryBean
|
||||
implements ResourceLoaderAware {
|
||||
|
||||
private static final String RESOURCE_PATTERN = "/**/*.class";
|
||||
|
||||
private static final String PACKAGE_INFO_SUFFIX = ".package-info";
|
||||
|
||||
|
||||
private Class<?>[] annotatedClasses;
|
||||
|
||||
private String[] annotatedPackages;
|
||||
|
||||
private String[] packagesToScan;
|
||||
|
||||
private TypeFilter[] entityTypeFilters = new TypeFilter[] {
|
||||
new AnnotationTypeFilter(Entity.class, false),
|
||||
new AnnotationTypeFilter(Embeddable.class, false),
|
||||
new AnnotationTypeFilter(MappedSuperclass.class, false),
|
||||
new AnnotationTypeFilter(org.hibernate.annotations.Entity.class, false)};
|
||||
|
||||
private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
|
||||
|
||||
|
||||
/**
|
||||
* Specify annotated classes, for which mappings will be read from
|
||||
* class-level annotation metadata.
|
||||
* @see org.hibernate.cfg.Configuration#addAnnotatedClass(Class)
|
||||
*/
|
||||
public void setAnnotatedClasses(Class<?>... annotatedClasses) {
|
||||
this.annotatedClasses = annotatedClasses;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the names of annotated packages, for which package-level
|
||||
* annotation metadata will be read.
|
||||
* @see org.hibernate.cfg.Configuration#addPackage(String)
|
||||
*/
|
||||
public void setAnnotatedPackages(String... annotatedPackages) {
|
||||
this.annotatedPackages = annotatedPackages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify packages to search using Spring-based scanning for entity classes in
|
||||
* the classpath. This is an alternative to listing annotated classes explicitly.
|
||||
* <p>Default is none. Specify packages to search for autodetection of your entity
|
||||
* classes in the classpath. This is analogous to Spring's component-scan feature
|
||||
* ({@link org.springframework.context.annotation.ClassPathBeanDefinitionScanner}).
|
||||
*/
|
||||
public void setPackagesToScan(String... packagesToScan) {
|
||||
this.packagesToScan = packagesToScan;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify custom type filters for Spring-based scanning for entity classes.
|
||||
* <p>Default is to search all specified packages for classes annotated with
|
||||
* {@code @javax.persistence.Entity}, {@code @javax.persistence.Embeddable}
|
||||
* or {@code @javax.persistence.MappedSuperclass}, as well as for
|
||||
* Hibernate's special {@code @org.hibernate.annotations.Entity}.
|
||||
* @see #setPackagesToScan
|
||||
*/
|
||||
public void setEntityTypeFilters(TypeFilter... entityTypeFilters) {
|
||||
this.entityTypeFilters = entityTypeFilters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setResourceLoader(ResourceLoader resourceLoader) {
|
||||
this.resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reads metadata from annotated classes and packages into the
|
||||
* AnnotationConfiguration instance.
|
||||
*/
|
||||
@Override
|
||||
protected void postProcessMappings(Configuration config) throws HibernateException {
|
||||
if (this.annotatedClasses != null) {
|
||||
for (Class<?> annotatedClass : this.annotatedClasses) {
|
||||
config.addAnnotatedClass(annotatedClass);
|
||||
}
|
||||
}
|
||||
if (this.annotatedPackages != null) {
|
||||
for (String annotatedPackage : this.annotatedPackages) {
|
||||
config.addPackage(annotatedPackage);
|
||||
}
|
||||
}
|
||||
scanPackages(config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform Spring-based scanning for entity classes.
|
||||
* @see #setPackagesToScan
|
||||
*/
|
||||
protected void scanPackages(Configuration config) {
|
||||
if (this.packagesToScan != null) {
|
||||
Set<String> classNames = new TreeSet<String>();
|
||||
Set<String> packageNames = new TreeSet<String>();
|
||||
try {
|
||||
for (String pkg : this.packagesToScan) {
|
||||
String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
|
||||
ClassUtils.convertClassNameToResourcePath(pkg) + RESOURCE_PATTERN;
|
||||
Resource[] resources = this.resourcePatternResolver.getResources(pattern);
|
||||
MetadataReaderFactory readerFactory = new CachingMetadataReaderFactory(this.resourcePatternResolver);
|
||||
for (Resource resource : resources) {
|
||||
if (resource.isReadable()) {
|
||||
MetadataReader reader = readerFactory.getMetadataReader(resource);
|
||||
String className = reader.getClassMetadata().getClassName();
|
||||
if (matchesEntityTypeFilter(reader, readerFactory)) {
|
||||
classNames.add(className);
|
||||
}
|
||||
else if (className.endsWith(PACKAGE_INFO_SUFFIX)) {
|
||||
packageNames.add(className.substring(0, className.length() - PACKAGE_INFO_SUFFIX.length()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new MappingException("Failed to scan classpath for unlisted classes", ex);
|
||||
}
|
||||
try {
|
||||
for (String className : classNames) {
|
||||
config.addAnnotatedClass(this.resourcePatternResolver.getClassLoader().loadClass(className));
|
||||
}
|
||||
for (String packageName : packageNames) {
|
||||
config.addPackage(packageName);
|
||||
}
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
throw new MappingException("Failed to load annotated classes from classpath", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether any of the configured entity type filters matches
|
||||
* the current class descriptor contained in the metadata reader.
|
||||
*/
|
||||
private boolean matchesEntityTypeFilter(MetadataReader reader, MetadataReaderFactory readerFactory) throws IOException {
|
||||
if (this.entityTypeFilters != null) {
|
||||
for (TypeFilter filter : this.entityTypeFilters) {
|
||||
if (filter.match(reader, readerFactory)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
/**
|
||||
* Support package for the Hibernate 3 Annotation add-on,
|
||||
* which supports JPA-compliant Java 5+ annotations for mappings.
|
||||
*/
|
||||
package org.springframework.orm.hibernate3.annotation;
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
/**
|
||||
* Package providing integration of
|
||||
* <a href="http://www.hibernate.org">Hibernate 3.x</a>
|
||||
* with Spring concepts.
|
||||
*
|
||||
* <p>Contains SessionFactory helper classes, a template plus callback
|
||||
* for Hibernate access, and an implementation of Spring's transaction SPI
|
||||
* for local Hibernate transactions.
|
||||
*
|
||||
* <p><b>This package supports Hibernate 3.x only.</b>
|
||||
* See the {@code org.springframework.orm.hibernate4} package for Hibernate 4.x support.
|
||||
*/
|
||||
package org.springframework.orm.hibernate3;
|
||||
|
|
@ -1,223 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate3.support;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import javax.transaction.TransactionManager;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.usertype.UserType;
|
||||
import org.hibernate.util.EqualsHelper;
|
||||
|
||||
import org.springframework.jdbc.support.lob.LobCreator;
|
||||
import org.springframework.jdbc.support.lob.LobCreatorUtils;
|
||||
import org.springframework.jdbc.support.lob.LobHandler;
|
||||
|
||||
/**
|
||||
* Abstract base class for Hibernate UserType implementations that map to LOBs.
|
||||
* Retrieves the LobHandler to use from LocalSessionFactoryBean at config time.
|
||||
*
|
||||
* <p>For writing LOBs, either an active Spring transaction synchronization
|
||||
* or an active JTA transaction (with "jtaTransactionManager" specified on
|
||||
* LocalSessionFactoryBean or a Hibernate TransactionManagerLookup configured
|
||||
* through the corresponding Hibernate property) is required.
|
||||
*
|
||||
* <p>Offers template methods for setting parameters and getting result values,
|
||||
* passing in the LobHandler or LobCreator to use.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @see org.springframework.jdbc.support.lob.LobHandler
|
||||
* @see org.springframework.jdbc.support.lob.LobCreator
|
||||
* @see org.springframework.orm.hibernate3.LocalSessionFactoryBean#setLobHandler
|
||||
* @see org.springframework.orm.hibernate3.LocalSessionFactoryBean#setJtaTransactionManager
|
||||
* @deprecated as of Spring 4.3, in favor of Hibernate 4.x/5.x
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract class AbstractLobType implements UserType {
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private final LobHandler lobHandler;
|
||||
|
||||
private final TransactionManager jtaTransactionManager;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor used by Hibernate: fetches config-time LobHandler and
|
||||
* config-time JTA TransactionManager from LocalSessionFactoryBean.
|
||||
* @see org.springframework.orm.hibernate3.LocalSessionFactoryBean#getConfigTimeLobHandler
|
||||
* @see org.springframework.orm.hibernate3.LocalSessionFactoryBean#getConfigTimeTransactionManager
|
||||
*/
|
||||
protected AbstractLobType() {
|
||||
this(org.springframework.orm.hibernate3.LocalSessionFactoryBean.getConfigTimeLobHandler(),
|
||||
org.springframework.orm.hibernate3.LocalSessionFactoryBean.getConfigTimeTransactionManager());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor used for testing: takes an explicit LobHandler
|
||||
* and an explicit JTA TransactionManager (can be {@code null}).
|
||||
*/
|
||||
protected AbstractLobType(LobHandler lobHandler, TransactionManager jtaTransactionManager) {
|
||||
this.lobHandler = lobHandler;
|
||||
this.jtaTransactionManager = jtaTransactionManager;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This implementation returns false.
|
||||
*/
|
||||
@Override
|
||||
public boolean isMutable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation delegates to the Hibernate EqualsHelper.
|
||||
* @see org.hibernate.util.EqualsHelper#equals
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object x, Object y) throws HibernateException {
|
||||
return EqualsHelper.equals(x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation returns the hashCode of the given objectz.
|
||||
*/
|
||||
@Override
|
||||
public int hashCode(Object x) throws HibernateException {
|
||||
return x.hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation returns the passed-in value as-is.
|
||||
*/
|
||||
@Override
|
||||
public Object deepCopy(Object value) throws HibernateException {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation returns the passed-in value as-is.
|
||||
*/
|
||||
@Override
|
||||
public Serializable disassemble(Object value) throws HibernateException {
|
||||
return (Serializable) value;
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation returns the passed-in value as-is.
|
||||
*/
|
||||
@Override
|
||||
public Object assemble(Serializable cached, Object owner) throws HibernateException {
|
||||
return cached;
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation returns the passed-in original as-is.
|
||||
*/
|
||||
@Override
|
||||
public Object replace(Object original, Object target, Object owner) throws HibernateException {
|
||||
return original;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This implementation delegates to nullSafeGetInternal,
|
||||
* passing in the LobHandler of this type.
|
||||
* @see #nullSafeGetInternal
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public final Object nullSafeGet(ResultSet rs, String[] names, Object owner)
|
||||
throws HibernateException, SQLException {
|
||||
|
||||
if (this.lobHandler == null) {
|
||||
throw new IllegalStateException("No LobHandler found for configuration - " +
|
||||
"lobHandler property must be set on LocalSessionFactoryBean");
|
||||
}
|
||||
|
||||
try {
|
||||
return nullSafeGetInternal(rs, names, owner, this.lobHandler);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new HibernateException("I/O errors during LOB access", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation delegates to nullSafeSetInternal,
|
||||
* passing in a transaction-synchronized LobCreator for the
|
||||
* LobHandler of this type.
|
||||
* @see #nullSafeSetInternal
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public final void nullSafeSet(PreparedStatement st, Object value, int index)
|
||||
throws HibernateException, SQLException {
|
||||
|
||||
if (this.lobHandler == null) {
|
||||
throw new IllegalStateException("No LobHandler found for configuration - " +
|
||||
"lobHandler property must be set on LocalSessionFactoryBean");
|
||||
}
|
||||
|
||||
LobCreator lobCreator = this.lobHandler.getLobCreator();
|
||||
try {
|
||||
nullSafeSetInternal(st, index, value, lobCreator);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new HibernateException("I/O errors during LOB access", ex);
|
||||
}
|
||||
LobCreatorUtils.registerTransactionSynchronization(lobCreator, this.jtaTransactionManager);
|
||||
}
|
||||
|
||||
/**
|
||||
* Template method to extract a value from the given result set.
|
||||
* @param rs the ResultSet to extract from
|
||||
* @param names the column names
|
||||
* @param owner the containing entity
|
||||
* @param lobHandler the LobHandler to use
|
||||
* @return the extracted value
|
||||
* @throws SQLException if thrown by JDBC methods
|
||||
* @throws IOException if thrown by streaming methods
|
||||
* @throws HibernateException in case of any other exceptions
|
||||
*/
|
||||
protected abstract Object nullSafeGetInternal(
|
||||
ResultSet rs, String[] names, Object owner, LobHandler lobHandler)
|
||||
throws SQLException, IOException, HibernateException;
|
||||
|
||||
/**
|
||||
* Template method to set the given parameter value on the given statement.
|
||||
* @param ps the PreparedStatement to set on
|
||||
* @param index the statement parameter index
|
||||
* @param value the value to set
|
||||
* @param lobCreator the LobCreator to use
|
||||
* @throws SQLException if thrown by JDBC methods
|
||||
* @throws IOException if thrown by streaming methods
|
||||
* @throws HibernateException in case of any other exceptions
|
||||
*/
|
||||
protected abstract void nullSafeSetInternal(
|
||||
PreparedStatement ps, int index, Object value, LobCreator lobCreator)
|
||||
throws SQLException, IOException, HibernateException;
|
||||
|
||||
}
|
||||
|
|
@ -1,120 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate3.support;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.hibernate.SessionFactory;
|
||||
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
import org.springframework.web.context.request.async.CallableProcessingInterceptorAdapter;
|
||||
import org.springframework.web.context.request.async.DeferredResult;
|
||||
import org.springframework.web.context.request.async.DeferredResultProcessingInterceptor;
|
||||
|
||||
/**
|
||||
* An interceptor with asynchronous web requests used in OpenSessionInViewFilter and
|
||||
* OpenSessionInViewInterceptor.
|
||||
*
|
||||
* Ensures the following:
|
||||
* 1) The session is bound/unbound when "callable processing" is started
|
||||
* 2) The session is closed if an async request times out
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 3.2.5
|
||||
* @deprecated as of Spring 4.3, in favor of Hibernate 4.x/5.x
|
||||
*/
|
||||
@Deprecated
|
||||
class AsyncRequestInterceptor extends CallableProcessingInterceptorAdapter implements DeferredResultProcessingInterceptor {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(AsyncRequestInterceptor.class);
|
||||
|
||||
private final SessionFactory sessionFactory;
|
||||
|
||||
private final org.springframework.orm.hibernate3.SessionHolder sessionHolder;
|
||||
|
||||
private volatile boolean timeoutInProgress;
|
||||
|
||||
|
||||
public AsyncRequestInterceptor(SessionFactory sessionFactory, org.springframework.orm.hibernate3.SessionHolder sessionHolder) {
|
||||
this.sessionFactory = sessionFactory;
|
||||
this.sessionHolder = sessionHolder;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public <T> void preProcess(NativeWebRequest request, Callable<T> task) {
|
||||
bindSession();
|
||||
}
|
||||
|
||||
public void bindSession() {
|
||||
this.timeoutInProgress = false;
|
||||
TransactionSynchronizationManager.bindResource(this.sessionFactory, this.sessionHolder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void postProcess(NativeWebRequest request, Callable<T> task, Object concurrentResult) {
|
||||
TransactionSynchronizationManager.unbindResource(this.sessionFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Object handleTimeout(NativeWebRequest request, Callable<T> task) {
|
||||
this.timeoutInProgress = true;
|
||||
return RESULT_NONE; // give other interceptors a chance to handle the timeout
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void afterCompletion(NativeWebRequest request, Callable<T> task) throws Exception {
|
||||
closeAfterTimeout();
|
||||
}
|
||||
|
||||
private void closeAfterTimeout() {
|
||||
if (this.timeoutInProgress) {
|
||||
logger.debug("Closing Hibernate Session after async request timeout");
|
||||
org.springframework.orm.hibernate3.SessionFactoryUtils.closeSession(this.sessionHolder.getSession());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Implementation of DeferredResultProcessingInterceptor methods
|
||||
|
||||
@Override
|
||||
public <T> void beforeConcurrentHandling(NativeWebRequest request, DeferredResult<T> deferredResult) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void preProcess(NativeWebRequest request, DeferredResult<T> deferredResult) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void postProcess(NativeWebRequest request, DeferredResult<T> deferredResult, Object result) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> boolean handleTimeout(NativeWebRequest request, DeferredResult<T> deferredResult) {
|
||||
this.timeoutInProgress = true;
|
||||
return true; // give other interceptors a chance to handle the timeout
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void afterCompletion(NativeWebRequest request, DeferredResult<T> deferredResult) {
|
||||
closeAfterTimeout();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,112 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate3.support;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import java.util.Arrays;
|
||||
import javax.transaction.TransactionManager;
|
||||
|
||||
import org.springframework.jdbc.support.lob.LobCreator;
|
||||
import org.springframework.jdbc.support.lob.LobHandler;
|
||||
|
||||
/**
|
||||
* Hibernate UserType implementation for byte arrays that get mapped to BLOBs.
|
||||
* Retrieves the LobHandler to use from LocalSessionFactoryBean at config time.
|
||||
*
|
||||
* <p>Can also be defined in generic Hibernate mappings, as DefaultLobCreator will
|
||||
* work with most JDBC-compliant database drivers. In this case, the field type
|
||||
* does not have to be BLOB: For databases like MySQL and MS SQL Server, any
|
||||
* large enough binary type will work.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @see org.springframework.orm.hibernate3.LocalSessionFactoryBean#setLobHandler
|
||||
* @deprecated as of Spring 4.3, in favor of Hibernate 4.x/5.x
|
||||
*/
|
||||
@Deprecated
|
||||
public class BlobByteArrayType extends AbstractLobType {
|
||||
|
||||
/**
|
||||
* Constructor used by Hibernate: fetches config-time LobHandler and
|
||||
* config-time JTA TransactionManager from LocalSessionFactoryBean.
|
||||
* @see org.springframework.orm.hibernate3.LocalSessionFactoryBean#getConfigTimeLobHandler
|
||||
* @see org.springframework.orm.hibernate3.LocalSessionFactoryBean#getConfigTimeTransactionManager
|
||||
*/
|
||||
public BlobByteArrayType() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor used for testing: takes an explicit LobHandler
|
||||
* and an explicit JTA TransactionManager (can be {@code null}).
|
||||
*/
|
||||
protected BlobByteArrayType(LobHandler lobHandler, TransactionManager jtaTransactionManager) {
|
||||
super(lobHandler, jtaTransactionManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] sqlTypes() {
|
||||
return new int[] {Types.BLOB};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> returnedClass() {
|
||||
return byte[].class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMutable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object x, Object y) {
|
||||
return (x == y) ||
|
||||
(x instanceof byte[] && y instanceof byte[] && Arrays.equals((byte[]) x, (byte[]) y));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object deepCopy(Object value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
byte[] original = (byte[]) value;
|
||||
byte[] copy = new byte[original.length];
|
||||
System.arraycopy(original, 0, copy, 0, original.length);
|
||||
return copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object nullSafeGetInternal(
|
||||
ResultSet rs, String[] names, Object owner, LobHandler lobHandler)
|
||||
throws SQLException {
|
||||
|
||||
return lobHandler.getBlobAsBytes(rs, names[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void nullSafeSetInternal(
|
||||
PreparedStatement ps, int index, Object value, LobCreator lobCreator)
|
||||
throws SQLException {
|
||||
|
||||
lobCreator.setBlobAsBytes(ps, index, (byte[]) value);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,171 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate3.support;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import javax.transaction.TransactionManager;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
|
||||
import org.springframework.jdbc.support.lob.LobCreator;
|
||||
import org.springframework.jdbc.support.lob.LobHandler;
|
||||
|
||||
/**
|
||||
* Hibernate UserType implementation for arbitrary objects that get serialized to BLOBs.
|
||||
* Retrieves the LobHandler to use from LocalSessionFactoryBean at config time.
|
||||
*
|
||||
* <p>Can also be defined in generic Hibernate mappings, as DefaultLobCreator will
|
||||
* work with most JDBC-compliant database drivers. In this case, the field type
|
||||
* does not have to be BLOB: For databases like MySQL and MS SQL Server, any
|
||||
* large enough binary type will work.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @see org.springframework.orm.hibernate3.LocalSessionFactoryBean#setLobHandler
|
||||
* @deprecated as of Spring 4.3, in favor of Hibernate 4.x/5.x
|
||||
*/
|
||||
@Deprecated
|
||||
public class BlobSerializableType extends AbstractLobType {
|
||||
|
||||
/**
|
||||
* Initial size for ByteArrayOutputStreams used for serialization output.
|
||||
* <p>If a serialized object is larger than these 1024 bytes, the size of
|
||||
* the byte array used by the output stream will be doubled each time the
|
||||
* limit is reached.
|
||||
*/
|
||||
private static final int OUTPUT_BYTE_ARRAY_INITIAL_SIZE = 1024;
|
||||
|
||||
/**
|
||||
* Constructor used by Hibernate: fetches config-time LobHandler and
|
||||
* config-time JTA TransactionManager from LocalSessionFactoryBean.
|
||||
* @see org.springframework.orm.hibernate3.LocalSessionFactoryBean#getConfigTimeLobHandler
|
||||
* @see org.springframework.orm.hibernate3.LocalSessionFactoryBean#getConfigTimeTransactionManager
|
||||
*/
|
||||
public BlobSerializableType() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor used for testing: takes an explicit LobHandler
|
||||
* and an explicit JTA TransactionManager (can be {@code null}).
|
||||
*/
|
||||
protected BlobSerializableType(LobHandler lobHandler, TransactionManager jtaTransactionManager) {
|
||||
super(lobHandler, jtaTransactionManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] sqlTypes() {
|
||||
return new int[] {Types.BLOB};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> returnedClass() {
|
||||
return Serializable.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMutable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object deepCopy(Object value) throws HibernateException {
|
||||
try {
|
||||
// Write to new byte array to clone.
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(OUTPUT_BYTE_ARRAY_INITIAL_SIZE);
|
||||
ObjectOutputStream oos = new ObjectOutputStream(baos);
|
||||
try {
|
||||
oos.writeObject(value);
|
||||
}
|
||||
finally {
|
||||
oos.close();
|
||||
}
|
||||
|
||||
// Read it back and return a true copy.
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
|
||||
ObjectInputStream ois = new ObjectInputStream(bais);
|
||||
try {
|
||||
return ois.readObject();
|
||||
}
|
||||
finally {
|
||||
ois.close();
|
||||
}
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
throw new HibernateException("Couldn't clone BLOB contents", ex);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new HibernateException("Couldn't clone BLOB contents", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object nullSafeGetInternal(
|
||||
ResultSet rs, String[] names, Object owner, LobHandler lobHandler)
|
||||
throws SQLException, IOException, HibernateException {
|
||||
|
||||
InputStream is = lobHandler.getBlobAsBinaryStream(rs, names[0]);
|
||||
if (is != null) {
|
||||
ObjectInputStream ois = new ObjectInputStream(is);
|
||||
try {
|
||||
return ois.readObject();
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
throw new HibernateException("Could not deserialize BLOB contents", ex);
|
||||
}
|
||||
finally {
|
||||
ois.close();
|
||||
}
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void nullSafeSetInternal(
|
||||
PreparedStatement ps, int index, Object value, LobCreator lobCreator)
|
||||
throws SQLException, IOException {
|
||||
|
||||
if (value != null) {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(OUTPUT_BYTE_ARRAY_INITIAL_SIZE);
|
||||
ObjectOutputStream oos = new ObjectOutputStream(baos);
|
||||
try {
|
||||
oos.writeObject(value);
|
||||
oos.flush();
|
||||
lobCreator.setBlobAsBytes(ps, index, baos.toByteArray());
|
||||
}
|
||||
finally {
|
||||
oos.close();
|
||||
}
|
||||
}
|
||||
else {
|
||||
lobCreator.setBlobAsBytes(ps, index, null);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,126 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate3.support;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import javax.transaction.TransactionManager;
|
||||
|
||||
import org.springframework.jdbc.support.lob.LobCreator;
|
||||
import org.springframework.jdbc.support.lob.LobHandler;
|
||||
|
||||
/**
|
||||
* Hibernate UserType implementation for Strings that get mapped to BLOBs.
|
||||
* Retrieves the LobHandler to use from LocalSessionFactoryBean at config time.
|
||||
*
|
||||
* <p>This is intended for the (arguably unnatural, but still common) case
|
||||
* where character data is stored in a binary LOB. This requires encoding
|
||||
* and decoding the characters within this UserType; see the javadoc of the
|
||||
* {@code getCharacterEncoding()} method.
|
||||
*
|
||||
* <p>Can also be defined in generic Hibernate mappings, as DefaultLobCreator will
|
||||
* work with most JDBC-compliant database drivers. In this case, the field type
|
||||
* does not have to be BLOB: For databases like MySQL and MS SQL Server, any
|
||||
* large enough binary type will work.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2.7
|
||||
* @see #getCharacterEncoding()
|
||||
* @see org.springframework.orm.hibernate3.LocalSessionFactoryBean#setLobHandler
|
||||
* @deprecated as of Spring 4.3, in favor of Hibernate 4.x/5.x
|
||||
*/
|
||||
@Deprecated
|
||||
public class BlobStringType extends AbstractLobType {
|
||||
|
||||
/**
|
||||
* Constructor used by Hibernate: fetches config-time LobHandler and
|
||||
* config-time JTA TransactionManager from LocalSessionFactoryBean.
|
||||
* @see org.springframework.orm.hibernate3.LocalSessionFactoryBean#getConfigTimeLobHandler
|
||||
* @see org.springframework.orm.hibernate3.LocalSessionFactoryBean#getConfigTimeTransactionManager
|
||||
*/
|
||||
public BlobStringType() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor used for testing: takes an explicit LobHandler
|
||||
* and an explicit JTA TransactionManager (can be {@code null}).
|
||||
*/
|
||||
protected BlobStringType(LobHandler lobHandler, TransactionManager jtaTransactionManager) {
|
||||
super(lobHandler, jtaTransactionManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] sqlTypes() {
|
||||
return new int[] {Types.BLOB};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> returnedClass() {
|
||||
return String.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object nullSafeGetInternal(
|
||||
ResultSet rs, String[] names, Object owner, LobHandler lobHandler)
|
||||
throws SQLException, UnsupportedEncodingException {
|
||||
|
||||
byte[] bytes = lobHandler.getBlobAsBytes(rs, names[0]);
|
||||
if (bytes != null) {
|
||||
String encoding = getCharacterEncoding();
|
||||
return (encoding != null ? new String(bytes, encoding) : new String(bytes));
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void nullSafeSetInternal(
|
||||
PreparedStatement ps, int index, Object value, LobCreator lobCreator)
|
||||
throws SQLException, UnsupportedEncodingException {
|
||||
|
||||
if (value != null) {
|
||||
String str = (String) value;
|
||||
String encoding = getCharacterEncoding();
|
||||
byte[] bytes = (encoding != null ? str.getBytes(encoding) : str.getBytes());
|
||||
lobCreator.setBlobAsBytes(ps, index, bytes);
|
||||
}
|
||||
else {
|
||||
lobCreator.setBlobAsBytes(ps, index, null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the character encoding to apply to the BLOB's bytes
|
||||
* to turn them into a String.
|
||||
* <p>Default is {@code null}, indicating to use the platform
|
||||
* default encoding. To be overridden in subclasses for a specific
|
||||
* encoding such as "ISO-8859-1" or "UTF-8".
|
||||
* @return the character encoding to use, or {@code null}
|
||||
* to use the platform default encoding
|
||||
* @see String#String(byte[], String)
|
||||
* @see String#getBytes(String)
|
||||
*/
|
||||
protected String getCharacterEncoding() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,92 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate3.support;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import javax.transaction.TransactionManager;
|
||||
|
||||
import org.springframework.jdbc.support.lob.LobCreator;
|
||||
import org.springframework.jdbc.support.lob.LobHandler;
|
||||
|
||||
/**
|
||||
* Hibernate UserType implementation for Strings that get mapped to CLOBs.
|
||||
* Retrieves the LobHandler to use from LocalSessionFactoryBean at config time.
|
||||
*
|
||||
* <p>Particularly useful for storing Strings with more than 4000 characters in an
|
||||
* Oracle database (only possible via CLOBs), in combination with OracleLobHandler.
|
||||
*
|
||||
* <p>Can also be defined in generic Hibernate mappings, as DefaultLobCreator will
|
||||
* work with most JDBC-compliant database drivers. In this case, the field type
|
||||
* does not have to be CLOB: For databases like MySQL and MS SQL Server, any
|
||||
* large enough character type will work.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @see org.springframework.orm.hibernate3.LocalSessionFactoryBean#setLobHandler
|
||||
* @deprecated as of Spring 4.3, in favor of Hibernate 4.x/5.x
|
||||
*/
|
||||
@Deprecated
|
||||
public class ClobStringType extends AbstractLobType {
|
||||
|
||||
/**
|
||||
* Constructor used by Hibernate: fetches config-time LobHandler and
|
||||
* config-time JTA TransactionManager from LocalSessionFactoryBean.
|
||||
* @see org.springframework.orm.hibernate3.LocalSessionFactoryBean#getConfigTimeLobHandler
|
||||
* @see org.springframework.orm.hibernate3.LocalSessionFactoryBean#getConfigTimeTransactionManager
|
||||
*/
|
||||
public ClobStringType() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor used for testing: takes an explicit LobHandler
|
||||
* and an explicit JTA TransactionManager (can be {@code null}).
|
||||
*/
|
||||
protected ClobStringType(LobHandler lobHandler, TransactionManager jtaTransactionManager) {
|
||||
super(lobHandler, jtaTransactionManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] sqlTypes() {
|
||||
return new int[] {Types.CLOB};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> returnedClass() {
|
||||
return String.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object nullSafeGetInternal(
|
||||
ResultSet rs, String[] names, Object owner, LobHandler lobHandler)
|
||||
throws SQLException {
|
||||
|
||||
return lobHandler.getClobAsString(rs, names[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void nullSafeSetInternal(
|
||||
PreparedStatement ps, int index, Object value, LobCreator lobCreator)
|
||||
throws SQLException {
|
||||
|
||||
lobCreator.setClobAsString(ps, index, (String) value);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,216 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate3.support;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.DataAccessResourceFailureException;
|
||||
import org.springframework.dao.support.DaoSupport;
|
||||
|
||||
/**
|
||||
* Convenient super class for Hibernate-based data access objects.
|
||||
*
|
||||
* <p>Requires a {@link org.hibernate.SessionFactory} to be set, providing a
|
||||
* {@link org.springframework.orm.hibernate3.HibernateTemplate} based on it to
|
||||
* subclasses through the {@link #getHibernateTemplate()} method.
|
||||
* Can alternatively be initialized directly with a HibernateTemplate,
|
||||
* in order to reuse the latter's settings such as the SessionFactory,
|
||||
* exception translator, flush mode, etc.
|
||||
*
|
||||
* <p>This base class is mainly intended for HibernateTemplate usage but can
|
||||
* also be used when working with a Hibernate Session directly, for example
|
||||
* when relying on transactional Sessions. Convenience {@link #getSession}
|
||||
* and {@link #releaseSession} methods are provided for that usage style.
|
||||
*
|
||||
* <p>This class will create its own HibernateTemplate instance if a SessionFactory
|
||||
* is passed in. The "allowCreate" flag on that HibernateTemplate will be "true"
|
||||
* by default. A custom HibernateTemplate instance can be used through overriding
|
||||
* {@link #createHibernateTemplate}.
|
||||
*
|
||||
* <p><b>NOTE: As of Hibernate 3.0.1, transactional Hibernate access code can
|
||||
* also be coded in plain Hibernate style. Hence, for newly started projects,
|
||||
* consider adopting the standard Hibernate3 style of coding data access objects
|
||||
* instead, based on {@link org.hibernate.SessionFactory#getCurrentSession()}.</b>
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @see #setSessionFactory
|
||||
* @see #getHibernateTemplate
|
||||
* @see org.springframework.orm.hibernate3.HibernateTemplate
|
||||
* @deprecated as of Spring 4.3, in favor of Hibernate 4.x/5.x
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract class HibernateDaoSupport extends DaoSupport {
|
||||
|
||||
private org.springframework.orm.hibernate3.HibernateTemplate hibernateTemplate;
|
||||
|
||||
|
||||
/**
|
||||
* Set the Hibernate SessionFactory to be used by this DAO.
|
||||
* Will automatically create a HibernateTemplate for the given SessionFactory.
|
||||
* @see #createHibernateTemplate
|
||||
* @see #setHibernateTemplate
|
||||
*/
|
||||
public final void setSessionFactory(SessionFactory sessionFactory) {
|
||||
if (this.hibernateTemplate == null || sessionFactory != this.hibernateTemplate.getSessionFactory()) {
|
||||
this.hibernateTemplate = createHibernateTemplate(sessionFactory);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a HibernateTemplate for the given SessionFactory.
|
||||
* Only invoked if populating the DAO with a SessionFactory reference!
|
||||
* <p>Can be overridden in subclasses to provide a HibernateTemplate instance
|
||||
* with different configuration, or a custom HibernateTemplate subclass.
|
||||
* @param sessionFactory the Hibernate SessionFactory to create a HibernateTemplate for
|
||||
* @return the new HibernateTemplate instance
|
||||
* @see #setSessionFactory
|
||||
*/
|
||||
protected org.springframework.orm.hibernate3.HibernateTemplate createHibernateTemplate(SessionFactory sessionFactory) {
|
||||
return new org.springframework.orm.hibernate3.HibernateTemplate(sessionFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Hibernate SessionFactory used by this DAO.
|
||||
*/
|
||||
public final SessionFactory getSessionFactory() {
|
||||
return (this.hibernateTemplate != null ? this.hibernateTemplate.getSessionFactory() : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the HibernateTemplate for this DAO explicitly,
|
||||
* as an alternative to specifying a SessionFactory.
|
||||
* @see #setSessionFactory
|
||||
*/
|
||||
public final void setHibernateTemplate(org.springframework.orm.hibernate3.HibernateTemplate hibernateTemplate) {
|
||||
this.hibernateTemplate = hibernateTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the HibernateTemplate for this DAO,
|
||||
* pre-initialized with the SessionFactory or set explicitly.
|
||||
* <p><b>Note: The returned HibernateTemplate is a shared instance.</b>
|
||||
* You may introspect its configuration, but not modify the configuration
|
||||
* (other than from within an {@link #initDao} implementation).
|
||||
* Consider creating a custom HibernateTemplate instance via
|
||||
* {@code new HibernateTemplate(getSessionFactory())}, in which case
|
||||
* you're allowed to customize the settings on the resulting instance.
|
||||
*/
|
||||
public final org.springframework.orm.hibernate3.HibernateTemplate getHibernateTemplate() {
|
||||
return this.hibernateTemplate;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void checkDaoConfig() {
|
||||
if (this.hibernateTemplate == null) {
|
||||
throw new IllegalArgumentException("'sessionFactory' or 'hibernateTemplate' is required");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Obtain a Hibernate Session, either from the current transaction or
|
||||
* a new one. The latter is only allowed if the
|
||||
* {@link org.springframework.orm.hibernate3.HibernateTemplate#setAllowCreate "allowCreate"}
|
||||
* setting of this bean's {@link #setHibernateTemplate HibernateTemplate} is "true".
|
||||
* <p><b>Note that this is not meant to be invoked from HibernateTemplate code
|
||||
* but rather just in plain Hibernate code.</b> Either rely on a thread-bound
|
||||
* Session or use it in combination with {@link #releaseSession}.
|
||||
* <p>In general, it is recommended to use HibernateTemplate, either with
|
||||
* the provided convenience operations or with a custom HibernateCallback
|
||||
* that provides you with a Session to work on. HibernateTemplate will care
|
||||
* for all resource management and for proper exception conversion.
|
||||
* @return the Hibernate Session
|
||||
* @throws DataAccessResourceFailureException if the Session couldn't be created
|
||||
* @throws IllegalStateException if no thread-bound Session found and allowCreate=false
|
||||
* @see org.springframework.orm.hibernate3.SessionFactoryUtils#getSession(SessionFactory, boolean)
|
||||
* @deprecated as of Spring 3.2.7, in favor of {@link org.springframework.orm.hibernate3.HibernateTemplate} usage
|
||||
*/
|
||||
@Deprecated
|
||||
protected final Session getSession() throws DataAccessResourceFailureException, IllegalStateException {
|
||||
return getSession(this.hibernateTemplate.isAllowCreate());
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain a Hibernate Session, either from the current transaction or
|
||||
* a new one. The latter is only allowed if "allowCreate" is true.
|
||||
* <p><b>Note that this is not meant to be invoked from HibernateTemplate code
|
||||
* but rather just in plain Hibernate code.</b> Either rely on a thread-bound
|
||||
* Session or use it in combination with {@link #releaseSession}.
|
||||
* <p>In general, it is recommended to use
|
||||
* {@link #getHibernateTemplate() HibernateTemplate}, either with
|
||||
* the provided convenience operations or with a custom
|
||||
* {@link org.springframework.orm.hibernate3.HibernateCallback} that
|
||||
* provides you with a Session to work on. HibernateTemplate will care
|
||||
* for all resource management and for proper exception conversion.
|
||||
* @param allowCreate if a non-transactional Session should be created when no
|
||||
* transactional Session can be found for the current thread
|
||||
* @return the Hibernate Session
|
||||
* @throws DataAccessResourceFailureException if the Session couldn't be created
|
||||
* @throws IllegalStateException if no thread-bound Session found and allowCreate=false
|
||||
* @see org.springframework.orm.hibernate3.SessionFactoryUtils#getSession(SessionFactory, boolean)
|
||||
* @deprecated as of Spring 3.2.7, in favor of {@link org.springframework.orm.hibernate3.HibernateTemplate} usage
|
||||
*/
|
||||
@Deprecated
|
||||
protected final Session getSession(boolean allowCreate)
|
||||
throws DataAccessResourceFailureException, IllegalStateException {
|
||||
|
||||
return (!allowCreate ?
|
||||
org.springframework.orm.hibernate3.SessionFactoryUtils.getSession(getSessionFactory(), false) :
|
||||
org.springframework.orm.hibernate3.SessionFactoryUtils.getSession(
|
||||
getSessionFactory(),
|
||||
this.hibernateTemplate.getEntityInterceptor(),
|
||||
this.hibernateTemplate.getJdbcExceptionTranslator()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given HibernateException to an appropriate exception from the
|
||||
* {@code org.springframework.dao} hierarchy. Will automatically detect
|
||||
* wrapped SQLExceptions and convert them accordingly.
|
||||
* <p>Delegates to the
|
||||
* {@link org.springframework.orm.hibernate3.HibernateTemplate#convertHibernateAccessException}
|
||||
* method of this DAO's HibernateTemplate.
|
||||
* <p>Typically used in plain Hibernate code, in combination with
|
||||
* {@link #getSession} and {@link #releaseSession}.
|
||||
* @param ex HibernateException that occurred
|
||||
* @return the corresponding DataAccessException instance
|
||||
* @see org.springframework.orm.hibernate3.SessionFactoryUtils#convertHibernateAccessException
|
||||
* @deprecated as of Spring 3.2.7, in favor of {@link org.springframework.orm.hibernate3.HibernateTemplate} usage
|
||||
*/
|
||||
@Deprecated
|
||||
protected final DataAccessException convertHibernateAccessException(HibernateException ex) {
|
||||
return this.hibernateTemplate.convertHibernateAccessException(ex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the given Hibernate Session, created via this DAO's SessionFactory,
|
||||
* if it isn't bound to the thread (i.e. isn't a transactional Session).
|
||||
* <p>Typically used in plain Hibernate code, in combination with
|
||||
* {@link #getSession} and {@link #convertHibernateAccessException}.
|
||||
* @param session the Session to close
|
||||
* @see org.springframework.orm.hibernate3.SessionFactoryUtils#releaseSession
|
||||
* @deprecated as of Spring 3.2.7, in favor of {@link org.springframework.orm.hibernate3.HibernateTemplate} usage
|
||||
*/
|
||||
@Deprecated
|
||||
protected final void releaseSession(Session session) {
|
||||
org.springframework.orm.hibernate3.SessionFactoryUtils.releaseSession(session, getSessionFactory());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate3.support;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.engine.SessionImplementor;
|
||||
import org.hibernate.event.MergeEvent;
|
||||
import org.hibernate.event.def.DefaultMergeEventListener;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
|
||||
/**
|
||||
* Extension of Hibernate's DefaultMergeEventListener, transferring the ids
|
||||
* of newly saved objects to the corresponding original objects (that are part
|
||||
* of the detached object graph passed into the {@code merge} method).
|
||||
*
|
||||
* <p>Transferring newly assigned ids to the original graph allows for continuing
|
||||
* to use the original object graph, despite merged copies being registered with
|
||||
* the current Hibernate Session. This is particularly useful for web applications
|
||||
* that might want to store an object graph and then render it in a web view,
|
||||
* with links that include the id of certain (potentially newly saved) objects.
|
||||
*
|
||||
* <p>The merge behavior given by this MergeEventListener is nearly identical
|
||||
* to TopLink's merge behavior. See PetClinic for an example, which relies on
|
||||
* ids being available for newly saved objects: the {@code HibernateClinic}
|
||||
* and {@code TopLinkClinic} DAO implementations both use straight merge
|
||||
* calls, with the Hibernate SessionFactory configuration specifying an
|
||||
* {@code IdTransferringMergeEventListener}.
|
||||
*
|
||||
* <p>Typically specified as entry for LocalSessionFactoryBean's "eventListeners"
|
||||
* map, with key "merge".
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @see org.springframework.orm.hibernate3.LocalSessionFactoryBean#setEventListeners(java.util.Map)
|
||||
* @deprecated as of Spring 4.3, in favor of Hibernate 4.x/5.x
|
||||
*/
|
||||
@Deprecated
|
||||
@SuppressWarnings({"serial", "rawtypes"})
|
||||
public class IdTransferringMergeEventListener extends DefaultMergeEventListener {
|
||||
|
||||
/**
|
||||
* Hibernate 3.1 implementation of ID transferral.
|
||||
*/
|
||||
@Override
|
||||
protected void entityIsTransient(MergeEvent event, Map copyCache) {
|
||||
super.entityIsTransient(event, copyCache);
|
||||
SessionImplementor session = event.getSession();
|
||||
EntityPersister persister = session.getEntityPersister(event.getEntityName(), event.getEntity());
|
||||
// Extract id from merged copy (which is currently registered with Session).
|
||||
Serializable id = persister.getIdentifier(event.getResult(), session.getEntityMode());
|
||||
// Set id on original object (which remains detached).
|
||||
persister.setIdentifier(event.getOriginal(), id, session.getEntityMode());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,324 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate3.support;
|
||||
|
||||
import java.io.IOException;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.hibernate.FlushMode;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
|
||||
import org.springframework.dao.DataAccessResourceFailureException;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.context.request.async.WebAsyncManager;
|
||||
import org.springframework.web.context.request.async.WebAsyncUtils;
|
||||
import org.springframework.web.context.support.WebApplicationContextUtils;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
/**
|
||||
* Servlet Filter that binds a Hibernate Session to the thread for the entire
|
||||
* processing of the request. Intended for the "Open Session in View" pattern,
|
||||
* i.e. to allow for lazy loading in web views despite the original transactions
|
||||
* already being completed.
|
||||
*
|
||||
* <p>This filter makes Hibernate Sessions available via the current thread, which
|
||||
* will be autodetected by transaction managers. It is suitable for service layer
|
||||
* transactions via {@link org.springframework.orm.hibernate3.HibernateTransactionManager}
|
||||
* or {@link org.springframework.transaction.jta.JtaTransactionManager} as well
|
||||
* as for non-transactional execution (if configured appropriately).
|
||||
*
|
||||
* <p><b>NOTE</b>: This filter will by default <i>not</i> flush the Hibernate Session,
|
||||
* with the flush mode set to {@code FlushMode.NEVER}. It assumes to be used
|
||||
* in combination with service layer transactions that care for the flushing: The
|
||||
* active transaction manager will temporarily change the flush mode to
|
||||
* {@code FlushMode.AUTO} during a read-write transaction, with the flush
|
||||
* mode reset to {@code FlushMode.NEVER} at the end of each transaction.
|
||||
* If you intend to use this filter without transactions, consider changing
|
||||
* the default flush mode (through the "flushMode" property).
|
||||
*
|
||||
* <p><b>WARNING:</b> Applying this filter to existing logic can cause issues that
|
||||
* have not appeared before, through the use of a single Hibernate Session for the
|
||||
* processing of an entire request. In particular, the reassociation of persistent
|
||||
* objects with a Hibernate Session has to occur at the very beginning of request
|
||||
* processing, to avoid clashes with already loaded instances of the same objects.
|
||||
*
|
||||
* <p>Alternatively, turn this filter into deferred close mode, by specifying
|
||||
* "singleSession"="false": It will not use a single session per request then,
|
||||
* but rather let each data access operation or transaction use its own session
|
||||
* (like without Open Session in View). Each of those sessions will be registered
|
||||
* for deferred close, though, actually processed at request completion.
|
||||
*
|
||||
* <p>A single session per request allows for most efficient first-level caching,
|
||||
* but can cause side effects, for example on {@code saveOrUpdate} or when
|
||||
* continuing after a rolled-back transaction. The deferred close strategy is as safe
|
||||
* as no Open Session in View in that respect, while still allowing for lazy loading
|
||||
* in views (but not providing a first-level cache for the entire request).
|
||||
*
|
||||
* <p>Looks up the SessionFactory in Spring's root web application context.
|
||||
* Supports a "sessionFactoryBeanName" filter init-param in {@code web.xml};
|
||||
* the default bean name is "sessionFactory".
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @see #setSingleSession
|
||||
* @see #setFlushMode
|
||||
* @see #lookupSessionFactory
|
||||
* @see OpenSessionInViewInterceptor
|
||||
* @see OpenSessionInterceptor
|
||||
* @see org.springframework.orm.hibernate3.HibernateTransactionManager
|
||||
* @see org.springframework.orm.hibernate3.SessionFactoryUtils#getSession
|
||||
* @see org.springframework.transaction.support.TransactionSynchronizationManager
|
||||
* @see org.hibernate.SessionFactory#getCurrentSession()
|
||||
* @deprecated as of Spring 4.3, in favor of Hibernate 4.x/5.x
|
||||
*/
|
||||
@Deprecated
|
||||
public class OpenSessionInViewFilter extends OncePerRequestFilter {
|
||||
|
||||
public static final String DEFAULT_SESSION_FACTORY_BEAN_NAME = "sessionFactory";
|
||||
|
||||
|
||||
private String sessionFactoryBeanName = DEFAULT_SESSION_FACTORY_BEAN_NAME;
|
||||
|
||||
private boolean singleSession = true;
|
||||
|
||||
private FlushMode flushMode = FlushMode.MANUAL;
|
||||
|
||||
|
||||
/**
|
||||
* Set the bean name of the SessionFactory to fetch from Spring's
|
||||
* root application context. Default is "sessionFactory".
|
||||
* @see #DEFAULT_SESSION_FACTORY_BEAN_NAME
|
||||
*/
|
||||
public void setSessionFactoryBeanName(String sessionFactoryBeanName) {
|
||||
this.sessionFactoryBeanName = sessionFactoryBeanName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the bean name of the SessionFactory to fetch from Spring's
|
||||
* root application context.
|
||||
*/
|
||||
protected String getSessionFactoryBeanName() {
|
||||
return this.sessionFactoryBeanName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether to use a single session for each request. Default is "true".
|
||||
* <p>If set to "false", each data access operation or transaction will use
|
||||
* its own session (like without Open Session in View). Each of those
|
||||
* sessions will be registered for deferred close, though, actually
|
||||
* processed at request completion.
|
||||
* @see org.springframework.orm.hibernate3.SessionFactoryUtils#initDeferredClose
|
||||
* @see org.springframework.orm.hibernate3.SessionFactoryUtils#processDeferredClose
|
||||
*/
|
||||
public void setSingleSession(boolean singleSession) {
|
||||
this.singleSession = singleSession;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether to use a single session for each request.
|
||||
*/
|
||||
protected boolean isSingleSession() {
|
||||
return this.singleSession;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the Hibernate FlushMode to apply to this filter's
|
||||
* {@link org.hibernate.Session}. Only applied in single session mode.
|
||||
* <p>Can be populated with the corresponding constant name in XML bean
|
||||
* definitions: e.g. "AUTO".
|
||||
* <p>The default is "MANUAL". Specify "AUTO" if you intend to use
|
||||
* this filter without service layer transactions.
|
||||
* @see org.hibernate.Session#setFlushMode
|
||||
* @see org.hibernate.FlushMode#MANUAL
|
||||
* @see org.hibernate.FlushMode#AUTO
|
||||
*/
|
||||
public void setFlushMode(FlushMode flushMode) {
|
||||
this.flushMode = flushMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Hibernate FlushMode that this filter applies to its
|
||||
* {@link org.hibernate.Session} (in single session mode).
|
||||
*/
|
||||
protected FlushMode getFlushMode() {
|
||||
return this.flushMode;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns "false" so that the filter may re-bind the opened Hibernate
|
||||
* {@code Session} to each asynchronously dispatched thread and postpone
|
||||
* closing it until the very last asynchronous dispatch.
|
||||
*/
|
||||
@Override
|
||||
protected boolean shouldNotFilterAsyncDispatch() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns "false" so that the filter may provide a Hibernate
|
||||
* {@code Session} to each error dispatches.
|
||||
*/
|
||||
@Override
|
||||
protected boolean shouldNotFilterErrorDispatch() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(
|
||||
HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
|
||||
throws ServletException, IOException {
|
||||
|
||||
SessionFactory sessionFactory = lookupSessionFactory(request);
|
||||
boolean participate = false;
|
||||
|
||||
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
|
||||
String key = getAlreadyFilteredAttributeName();
|
||||
|
||||
if (isSingleSession()) {
|
||||
// single session mode
|
||||
if (TransactionSynchronizationManager.hasResource(sessionFactory)) {
|
||||
// Do not modify the Session: just set the participate flag.
|
||||
participate = true;
|
||||
}
|
||||
else {
|
||||
boolean isFirstRequest = !isAsyncDispatch(request);
|
||||
if (isFirstRequest || !applySessionBindingInterceptor(asyncManager, key)) {
|
||||
logger.debug("Opening single Hibernate Session in OpenSessionInViewFilter");
|
||||
Session session = getSession(sessionFactory);
|
||||
org.springframework.orm.hibernate3.SessionHolder sessionHolder = new org.springframework.orm.hibernate3.SessionHolder(session);
|
||||
TransactionSynchronizationManager.bindResource(sessionFactory, sessionHolder);
|
||||
|
||||
AsyncRequestInterceptor interceptor = new AsyncRequestInterceptor(sessionFactory, sessionHolder);
|
||||
asyncManager.registerCallableInterceptor(key, interceptor);
|
||||
asyncManager.registerDeferredResultInterceptor(key, interceptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// deferred close mode
|
||||
Assert.state(!isAsyncStarted(request), "Deferred close mode is not supported on async dispatches");
|
||||
if (org.springframework.orm.hibernate3.SessionFactoryUtils.isDeferredCloseActive(sessionFactory)) {
|
||||
// Do not modify deferred close: just set the participate flag.
|
||||
participate = true;
|
||||
}
|
||||
else {
|
||||
org.springframework.orm.hibernate3.SessionFactoryUtils.initDeferredClose(sessionFactory);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
finally {
|
||||
if (!participate) {
|
||||
if (isSingleSession()) {
|
||||
// single session mode
|
||||
org.springframework.orm.hibernate3.SessionHolder sessionHolder =
|
||||
(org.springframework.orm.hibernate3.SessionHolder) TransactionSynchronizationManager.unbindResource(sessionFactory);
|
||||
if (!isAsyncStarted(request)) {
|
||||
logger.debug("Closing single Hibernate Session in OpenSessionInViewFilter");
|
||||
closeSession(sessionHolder.getSession(), sessionFactory);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// deferred close mode
|
||||
org.springframework.orm.hibernate3.SessionFactoryUtils.processDeferredClose(sessionFactory);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up the SessionFactory that this filter should use,
|
||||
* taking the current HTTP request as argument.
|
||||
* <p>The default implementation delegates to the {@link #lookupSessionFactory()}
|
||||
* variant without arguments.
|
||||
* @param request the current request
|
||||
* @return the SessionFactory to use
|
||||
*/
|
||||
protected SessionFactory lookupSessionFactory(HttpServletRequest request) {
|
||||
return lookupSessionFactory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up the SessionFactory that this filter should use.
|
||||
* <p>The default implementation looks for a bean with the specified name
|
||||
* in Spring's root application context.
|
||||
* @return the SessionFactory to use
|
||||
* @see #getSessionFactoryBeanName
|
||||
*/
|
||||
protected SessionFactory lookupSessionFactory() {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Using SessionFactory '" + getSessionFactoryBeanName() + "' for OpenSessionInViewFilter");
|
||||
}
|
||||
WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
|
||||
return wac.getBean(getSessionFactoryBeanName(), SessionFactory.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Session for the SessionFactory that this filter uses.
|
||||
* Note that this just applies in single session mode!
|
||||
* <p>The default implementation delegates to the
|
||||
* {@code SessionFactoryUtils.getSession} method and
|
||||
* sets the {@code Session}'s flush mode to "MANUAL".
|
||||
* <p>Can be overridden in subclasses for creating a Session with a
|
||||
* custom entity interceptor or JDBC exception translator.
|
||||
* @param sessionFactory the SessionFactory that this filter uses
|
||||
* @return the Session to use
|
||||
* @throws DataAccessResourceFailureException if the Session could not be created
|
||||
* @see org.springframework.orm.hibernate3.SessionFactoryUtils#getSession(SessionFactory, boolean)
|
||||
* @see org.hibernate.FlushMode#MANUAL
|
||||
*/
|
||||
protected Session getSession(SessionFactory sessionFactory) throws DataAccessResourceFailureException {
|
||||
Session session = org.springframework.orm.hibernate3.SessionFactoryUtils.getSession(sessionFactory, true);
|
||||
FlushMode flushMode = getFlushMode();
|
||||
if (flushMode != null) {
|
||||
session.setFlushMode(flushMode);
|
||||
}
|
||||
return session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the given Session.
|
||||
* Note that this just applies in single session mode!
|
||||
* <p>Can be overridden in subclasses, e.g. for flushing the Session before
|
||||
* closing it. See class-level javadoc for a discussion of flush handling.
|
||||
* Note that you should also override getSession accordingly, to set
|
||||
* the flush mode to something else than NEVER.
|
||||
* @param session the Session used for filtering
|
||||
* @param sessionFactory the SessionFactory that this filter uses
|
||||
*/
|
||||
protected void closeSession(Session session, SessionFactory sessionFactory) {
|
||||
org.springframework.orm.hibernate3.SessionFactoryUtils.closeSession(session);
|
||||
}
|
||||
|
||||
private boolean applySessionBindingInterceptor(WebAsyncManager asyncManager, String key) {
|
||||
if (asyncManager.getCallableInterceptor(key) == null) {
|
||||
return false;
|
||||
}
|
||||
((AsyncRequestInterceptor) asyncManager.getCallableInterceptor(key)).bindSession();
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,277 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate3.support;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.Session;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.context.request.AsyncWebRequestInterceptor;
|
||||
import org.springframework.web.context.request.WebRequest;
|
||||
import org.springframework.web.context.request.async.WebAsyncManager;
|
||||
import org.springframework.web.context.request.async.WebAsyncUtils;
|
||||
|
||||
/**
|
||||
* Spring web request interceptor that binds a Hibernate {@code Session} to the
|
||||
* thread for the entire processing of the request.
|
||||
*
|
||||
* <p>This class is a concrete expression of the "Open Session in View" pattern, which
|
||||
* is a pattern that allows for the lazy loading of associations in web views despite
|
||||
* the original transactions already being completed.
|
||||
*
|
||||
* <p>This interceptor makes Hibernate {@code Sessions} available via the current
|
||||
* thread, which will be autodetected by transaction managers. It is suitable for
|
||||
* service layer transactions via
|
||||
* {@link org.springframework.orm.hibernate3.HibernateTransactionManager} or
|
||||
* {@link org.springframework.transaction.jta.JtaTransactionManager} as well as for
|
||||
* non-transactional execution (if configured appropriately).
|
||||
*
|
||||
* <p><b>NOTE</b>: This interceptor will by default <i>not</i> flush the Hibernate
|
||||
* {@code Session}, with the flush mode being set to {@code FlushMode.NEVER}.
|
||||
* It assumes that it will be used in combination with service layer transactions
|
||||
* that handle the flushing: the active transaction manager will temporarily change
|
||||
* the flush mode to {@code FlushMode.AUTO} during a read-write transaction,
|
||||
* with the flush mode reset to {@code FlushMode.NEVER} at the end of each
|
||||
* transaction. If you intend to use this interceptor without transactions, consider
|
||||
* changing the default flush mode (through the
|
||||
* {@link #setFlushMode(int) "flushMode"} property).
|
||||
*
|
||||
* <p>In contrast to {@link OpenSessionInViewFilter}, this interceptor is
|
||||
* configured in a Spring application context and can thus take advantage of bean
|
||||
* wiring. It inherits common Hibernate configuration properties from
|
||||
* {@link org.springframework.orm.hibernate3.HibernateAccessor},
|
||||
* to be configured in a bean definition.
|
||||
*
|
||||
* <p><b>WARNING:</b> Applying this interceptor to existing logic can cause issues
|
||||
* that have not appeared before, through the use of a single Hibernate
|
||||
* {@code Session} for the processing of an entire request. In particular, the
|
||||
* reassociation of persistent objects with a Hibernate {@code Session} has to
|
||||
* occur at the very beginning of request processing, to avoid clashes with already
|
||||
* loaded instances of the same objects.
|
||||
*
|
||||
* <p>Alternatively, turn this interceptor into deferred close mode, by specifying
|
||||
* "singleSession"="false": It will not use a single session per request then,
|
||||
* but rather let each data access operation or transaction use its own session
|
||||
* (as would be the case without Open Session in View). Each of those sessions will
|
||||
* be registered for deferred close though, which will actually be processed at
|
||||
* request completion.
|
||||
*
|
||||
* <p>A single session per request allows for the most efficient first-level caching,
|
||||
* but can cause side effects, for example on {@code saveOrUpdate} or when
|
||||
* continuing after a rolled-back transaction. The deferred close strategy is as safe
|
||||
* as no Open Session in View in that respect, while still allowing for lazy loading
|
||||
* in views (but not providing a first-level cache for the entire request).
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @see #setSingleSession
|
||||
* @see #setFlushMode
|
||||
* @see OpenSessionInViewFilter
|
||||
* @see OpenSessionInterceptor
|
||||
* @see org.springframework.orm.hibernate3.HibernateTransactionManager
|
||||
* @see org.springframework.orm.hibernate3.SessionFactoryUtils#getSession
|
||||
* @see org.springframework.transaction.support.TransactionSynchronizationManager
|
||||
* @see org.hibernate.SessionFactory#getCurrentSession()
|
||||
* @deprecated as of Spring 4.3, in favor of Hibernate 4.x/5.x
|
||||
*/
|
||||
@Deprecated
|
||||
public class OpenSessionInViewInterceptor extends org.springframework.orm.hibernate3.HibernateAccessor implements AsyncWebRequestInterceptor {
|
||||
|
||||
/**
|
||||
* Suffix that gets appended to the {@code SessionFactory}
|
||||
* {@code toString()} representation for the "participate in existing
|
||||
* session handling" request attribute.
|
||||
* @see #getParticipateAttributeName
|
||||
*/
|
||||
public static final String PARTICIPATE_SUFFIX = ".PARTICIPATE";
|
||||
|
||||
|
||||
private boolean singleSession = true;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new {@code OpenSessionInViewInterceptor},
|
||||
* turning the default flushMode to {@code FLUSH_NEVER}.
|
||||
* @see #setFlushMode
|
||||
*/
|
||||
public OpenSessionInViewInterceptor() {
|
||||
setFlushMode(FLUSH_NEVER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether to use a single session for each request. Default is "true".
|
||||
* <p>If set to false, each data access operation or transaction will use
|
||||
* its own session (like without Open Session in View). Each of those
|
||||
* sessions will be registered for deferred close, though, actually
|
||||
* processed at request completion.
|
||||
* @see org.springframework.orm.hibernate3.SessionFactoryUtils#initDeferredClose
|
||||
* @see org.springframework.orm.hibernate3.SessionFactoryUtils#processDeferredClose
|
||||
*/
|
||||
public void setSingleSession(boolean singleSession) {
|
||||
this.singleSession = singleSession;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether to use a single session for each request.
|
||||
*/
|
||||
protected boolean isSingleSession() {
|
||||
return singleSession;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Open a new Hibernate {@code Session} according to the settings of this
|
||||
* {@code HibernateAccessor} and bind it to the thread via the
|
||||
* {@link TransactionSynchronizationManager}.
|
||||
* @see org.springframework.orm.hibernate3.SessionFactoryUtils#getSession
|
||||
*/
|
||||
@Override
|
||||
public void preHandle(WebRequest request) throws DataAccessException {
|
||||
String participateAttributeName = getParticipateAttributeName();
|
||||
|
||||
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
|
||||
if (asyncManager.hasConcurrentResult()) {
|
||||
if (applySessionBindingInterceptor(asyncManager, participateAttributeName)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ((isSingleSession() && TransactionSynchronizationManager.hasResource(getSessionFactory())) ||
|
||||
org.springframework.orm.hibernate3.SessionFactoryUtils.isDeferredCloseActive(getSessionFactory())) {
|
||||
// Do not modify the Session: just mark the request accordingly.
|
||||
Integer count = (Integer) request.getAttribute(participateAttributeName, WebRequest.SCOPE_REQUEST);
|
||||
int newCount = (count != null ? count + 1 : 1);
|
||||
request.setAttribute(getParticipateAttributeName(), newCount, WebRequest.SCOPE_REQUEST);
|
||||
}
|
||||
else {
|
||||
if (isSingleSession()) {
|
||||
// single session mode
|
||||
logger.debug("Opening single Hibernate Session in OpenSessionInViewInterceptor");
|
||||
Session session = org.springframework.orm.hibernate3.SessionFactoryUtils.getSession(
|
||||
getSessionFactory(), getEntityInterceptor(), getJdbcExceptionTranslator());
|
||||
applyFlushMode(session, false);
|
||||
org.springframework.orm.hibernate3.SessionHolder sessionHolder = new org.springframework.orm.hibernate3.SessionHolder(session);
|
||||
TransactionSynchronizationManager.bindResource(getSessionFactory(), sessionHolder);
|
||||
|
||||
AsyncRequestInterceptor asyncRequestInterceptor =
|
||||
new AsyncRequestInterceptor(getSessionFactory(), sessionHolder);
|
||||
asyncManager.registerCallableInterceptor(participateAttributeName, asyncRequestInterceptor);
|
||||
asyncManager.registerDeferredResultInterceptor(participateAttributeName, asyncRequestInterceptor);
|
||||
}
|
||||
else {
|
||||
// deferred close mode
|
||||
org.springframework.orm.hibernate3.SessionFactoryUtils.initDeferredClose(getSessionFactory());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush the Hibernate {@code Session} before view rendering, if necessary.
|
||||
* <p>Note that this just applies in {@link #isSingleSession() single session mode}!
|
||||
* <p>The default is {@code FLUSH_NEVER} to avoid this extra flushing,
|
||||
* assuming that service layer transactions have flushed their changes on commit.
|
||||
* @see #setFlushMode
|
||||
*/
|
||||
@Override
|
||||
public void postHandle(WebRequest request, ModelMap model) throws DataAccessException {
|
||||
if (isSingleSession()) {
|
||||
// Only potentially flush in single session mode.
|
||||
org.springframework.orm.hibernate3.SessionHolder sessionHolder =
|
||||
(org.springframework.orm.hibernate3.SessionHolder) TransactionSynchronizationManager.getResource(getSessionFactory());
|
||||
logger.debug("Flushing single Hibernate Session in OpenSessionInViewInterceptor");
|
||||
try {
|
||||
flushIfNecessary(sessionHolder.getSession(), false);
|
||||
}
|
||||
catch (HibernateException ex) {
|
||||
throw convertHibernateAccessException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unbind the Hibernate {@code Session} from the thread and close it (in
|
||||
* single session mode), or process deferred close for all sessions that have
|
||||
* been opened during the current request (in deferred close mode).
|
||||
* @see org.springframework.transaction.support.TransactionSynchronizationManager
|
||||
*/
|
||||
@Override
|
||||
public void afterCompletion(WebRequest request, Exception ex) throws DataAccessException {
|
||||
if (!decrementParticipateCount(request)) {
|
||||
if (isSingleSession()) {
|
||||
// single session mode
|
||||
org.springframework.orm.hibernate3.SessionHolder sessionHolder =
|
||||
(org.springframework.orm.hibernate3.SessionHolder) TransactionSynchronizationManager.unbindResource(getSessionFactory());
|
||||
logger.debug("Closing single Hibernate Session in OpenSessionInViewInterceptor");
|
||||
org.springframework.orm.hibernate3.SessionFactoryUtils.closeSession(sessionHolder.getSession());
|
||||
}
|
||||
else {
|
||||
// deferred close mode
|
||||
org.springframework.orm.hibernate3.SessionFactoryUtils.processDeferredClose(getSessionFactory());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterConcurrentHandlingStarted(WebRequest request) {
|
||||
if (!decrementParticipateCount(request)) {
|
||||
if (isSingleSession()) {
|
||||
TransactionSynchronizationManager.unbindResource(getSessionFactory());
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Deferred close mode is not supported with async requests.");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private boolean decrementParticipateCount(WebRequest request) {
|
||||
String participateAttributeName = getParticipateAttributeName();
|
||||
Integer count = (Integer) request.getAttribute(participateAttributeName, WebRequest.SCOPE_REQUEST);
|
||||
if (count == null) {
|
||||
return false;
|
||||
}
|
||||
// Do not modify the Session: just clear the marker.
|
||||
if (count > 1) {
|
||||
request.setAttribute(participateAttributeName, count - 1, WebRequest.SCOPE_REQUEST);
|
||||
}
|
||||
else {
|
||||
request.removeAttribute(participateAttributeName, WebRequest.SCOPE_REQUEST);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the request attribute that identifies that a request is
|
||||
* already intercepted.
|
||||
* <p>The default implementation takes the {@code toString()} representation
|
||||
* of the {@code SessionFactory} instance and appends {@link #PARTICIPATE_SUFFIX}.
|
||||
*/
|
||||
protected String getParticipateAttributeName() {
|
||||
return getSessionFactory().toString() + PARTICIPATE_SUFFIX;
|
||||
}
|
||||
|
||||
private boolean applySessionBindingInterceptor(WebAsyncManager asyncManager, String key) {
|
||||
if (asyncManager.getCallableInterceptor(key) == null) {
|
||||
return false;
|
||||
}
|
||||
((AsyncRequestInterceptor) asyncManager.getCallableInterceptor(key)).bindSession();
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,120 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate3.support;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.hibernate.FlushMode;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.dao.DataAccessResourceFailureException;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
|
||||
/**
|
||||
* Simple AOP Alliance {@link MethodInterceptor} implementation that binds a new
|
||||
* Hibernate {@link Session} for each method invocation, if none bound before.
|
||||
*
|
||||
* <p>This is a simple Hibernate Session scoping interceptor along the lines of
|
||||
* {@link OpenSessionInViewInterceptor}, just for use with AOP setup instead of
|
||||
* MVC setup. It opens a new {@link Session} with flush mode "MANUAL" since the
|
||||
* Session is only meant for reading, except when participating in a transaction.
|
||||
*
|
||||
* <p>Note: This can serve as a streamlined alternative to the outdated
|
||||
* {@link org.springframework.orm.hibernate3.HibernateInterceptor}, providing
|
||||
* plain Session binding without any automatic exception translation or the like.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.0.2
|
||||
* @see OpenSessionInViewInterceptor
|
||||
* @see OpenSessionInViewFilter
|
||||
* @see org.springframework.orm.hibernate3.HibernateTransactionManager
|
||||
* @see org.springframework.transaction.support.TransactionSynchronizationManager
|
||||
* @see org.hibernate.SessionFactory#getCurrentSession()
|
||||
* @deprecated as of Spring 4.3, in favor of Hibernate 4.x/5.x
|
||||
*/
|
||||
@Deprecated
|
||||
public class OpenSessionInterceptor implements MethodInterceptor, InitializingBean {
|
||||
|
||||
private SessionFactory sessionFactory;
|
||||
|
||||
|
||||
/**
|
||||
* Set the Hibernate SessionFactory that should be used to create Hibernate Sessions.
|
||||
*/
|
||||
public void setSessionFactory(SessionFactory sessionFactory) {
|
||||
this.sessionFactory = sessionFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Hibernate SessionFactory that should be used to create Hibernate Sessions.
|
||||
*/
|
||||
public SessionFactory getSessionFactory() {
|
||||
return this.sessionFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
if (getSessionFactory() == null) {
|
||||
throw new IllegalArgumentException("Property 'sessionFactory' is required");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object invoke(MethodInvocation invocation) throws Throwable {
|
||||
SessionFactory sf = getSessionFactory();
|
||||
if (!TransactionSynchronizationManager.hasResource(sf)) {
|
||||
// New Session to be bound for the current method's scope...
|
||||
Session session = openSession();
|
||||
try {
|
||||
TransactionSynchronizationManager.bindResource(sf, new org.springframework.orm.hibernate3.SessionHolder(session));
|
||||
return invocation.proceed();
|
||||
}
|
||||
finally {
|
||||
org.springframework.orm.hibernate3.SessionFactoryUtils.closeSession(session);
|
||||
TransactionSynchronizationManager.unbindResource(sf);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Pre-bound Session found -> simply proceed.
|
||||
return invocation.proceed();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a Session for the SessionFactory that this interceptor uses.
|
||||
* <p>The default implementation delegates to the {@link SessionFactory#openSession}
|
||||
* method and sets the {@link Session}'s flush mode to "MANUAL".
|
||||
* @return the Session to use
|
||||
* @throws DataAccessResourceFailureException if the Session could not be created
|
||||
* @see org.hibernate.FlushMode#MANUAL
|
||||
*/
|
||||
protected Session openSession() throws DataAccessResourceFailureException {
|
||||
try {
|
||||
Session session = getSessionFactory().openSession();
|
||||
session.setFlushMode(FlushMode.MANUAL);
|
||||
return session;
|
||||
}
|
||||
catch (HibernateException ex) {
|
||||
throw new DataAccessResourceFailureException("Could not open Hibernate Session", ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate3.support;
|
||||
|
||||
import org.hibernate.EmptyInterceptor;
|
||||
|
||||
import org.springframework.aop.scope.ScopedObject;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
|
||||
/**
|
||||
* Hibernate3 interceptor used for getting the proper entity name for scoped
|
||||
* beans. As scoped bean classes are proxies generated at runtime, they are
|
||||
* unrecognized by the persisting framework. Using this interceptor, the
|
||||
* original scoped bean class is retrieved end exposed to Hibernate for
|
||||
* persisting.
|
||||
*
|
||||
* <p>Usage example:
|
||||
*
|
||||
* <pre class="code">
|
||||
* <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
|
||||
* ...
|
||||
* <property name="entityInterceptor">
|
||||
* <bean class="org.springframework.orm.hibernate3.support.ScopedBeanInterceptor"/>
|
||||
* </property>
|
||||
* </bean></pre>
|
||||
*
|
||||
* @author Costin Leau
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
* @deprecated as of Spring 4.3, in favor of Hibernate 4.x/5.x
|
||||
*/
|
||||
@Deprecated
|
||||
@SuppressWarnings("serial")
|
||||
public class ScopedBeanInterceptor extends EmptyInterceptor {
|
||||
|
||||
@Override
|
||||
public String getEntityName(Object entity) {
|
||||
if (entity instanceof ScopedObject) {
|
||||
// Determine underlying object's type.
|
||||
Object targetObject = ((ScopedObject) entity).getTargetObject();
|
||||
return AopUtils.getTargetClass(targetObject).getName();
|
||||
}
|
||||
|
||||
// Any other object: delegate to the default implementation.
|
||||
return super.getEntityName(entity);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
/**
|
||||
* Classes supporting the {@code org.springframework.orm.hibernate3} package.
|
||||
* Contains a DAO base class for HibernateTemplate usage.
|
||||
*/
|
||||
package org.springframework.orm.hibernate3.support;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue