• Monthly Archives: 12月 2019

SpringBoot2.1.1整合hibernate5.0.12使用SessionFactory

1、在pom.xml中加入如下依赖:

		<!-- Spring的aspect切面支持 -->
		<!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
		<dependency>
		    <groupId>org.springframework</groupId>
		    <artifactId>spring-aspects</artifactId>
		    <version>4.2.5.RELEASE</version>
		</dependency>

		<!-- Spring的ORM(Hibernate)映射支持 -->
		<!-- https://mvnrepository.com/artifact/org.springframework/spring-orm -->
		<dependency>
		    <groupId>org.springframework</groupId>
		    <artifactId>spring-orm</artifactId>
		    <!-- <version>5.0.12.RELEASE</version>
		    <version>4.3.11.RELEASE</version> -->
		    <version>4.2.5.RELEASE</version>
		</dependency>

		<!-- Spring对Hibernate-SessionFactory的事务管理支持 -->
		<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core -->
		<dependency>
		    <groupId>org.hibernate</groupId>
		    <artifactId>hibernate-core</artifactId>
		    <version>5.0.12.Final</version>
		</dependency>

		<!-- mysql连接驱动 -->    
		<dependency>    
			<groupId>mysql</groupId>    
			<artifactId>mysql-connector-java</artifactId>    
			<version>5.1.9</version>
		</dependency>

如果pom.xml中有如下jpa依赖,记得清注释以下内容:

		<!-- SpringBoot对JPA的支持 -->
		<!-- <dependency>
		    <groupId>org.springframework.boot</groupId>
		    <artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency> -->

如果出现FilterRegistrationBean报错,则意味着缺少SpringMVC的filter依赖,办法之一是引入含有该filter的依赖(eureka的server依赖也是包含的):

		<!-- SpringMVC的配置 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
	        	<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

 

2、在application.properties中加入如下配置:

#mysql
spring.datasource.url=jdbc\:mysql\://localhost\:3306/xxxxx?useSSL\=false&characterEncoding\=utf8
spring.datasource.username=root
spring.datasource.password=
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

如果在低版本SpringBoot中进行配置,则可能会遇到错误“Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true”,此时则需要在application.properties补充配置:

spring.main.allow-bean-definition-overriding=true

因为SpringBoot的SessionFactory会自动注入默认的Transactional事务管理器,但这个事务管理器搭配hibernate的SessionFactory会出现数据库连接池线程卡死的问题,即假如配置线程池的连接数为10,一旦连接数大于10,则线程池会出现卡死的情况,因此我们需要自行配置hibernate的事务管理器来覆盖SpringBoot原有的Transactional事务管理器。

3、在SpringBoot的启动入口类上加入注解@ImportResource(“classpath:hibernate.xml”):

@SpringBootApplication
@ImportResource("classpath:hibernate.xml")
public class xxxxxApplication extends SpringBootServletInitializer{

	public static void main(String[] args) {
		SpringApplication.run(xxxxxApplication.class, args);
	}

}

4、在resources目录中加入配置文件hibernate.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jee="http://www.springframework.org/schema/jee"
	xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:p="http://www.springframework.org/schema/p" xmlns:util="http://www.springframework.org/schema/util"
	xmlns:tool="http://www.springframework.org/schema/tool" xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/tx
           http://www.springframework.org/schema/tx/spring-tx.xsd
           http://www.springframework.org/schema/aop
           http://www.springframework.org/schema/aop/spring-aop.xsd
           http://www.springframework.org/schema/jee
           http://www.springframework.org/schema/jee/spring-jee.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context.xsd
           http://www.springframework.org/schema/util
           http://www.springframework.org/schema/util/spring-util.xsd
           http://www.springframework.org/schema/tool
           http://www.springframework.org/schema/tool/spring-tool.xsd"
    default-autowire="no">
	
	<!-- hibernate sessionFactory 创建 -->
	<!-- hibernate.cfg.xml Spring config -->
	<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
		<!-- connection -->
		<property name="dataSource">
			<ref bean="dataSource" />
		</property>
		<!-- hibernate 类文件配置 -->
		<!-- hibernate自身属性 -->
		<property name="hibernateProperties">
			<props>
				<!-- 显示Hibernate 持久化操作所生成的SQL -->
				<prop key="hibernate.show_sql">false</prop>
				<!-- 将SQL脚本进行格式化后在输出 -->
				<prop key="hibernate.format_sql">true</prop>
				<!-- 指定数据库方言 -->
				<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
				<!-- **************** -->
				<prop key="hibernate.hbm2ddl.auto">update</prop>
				<!-- 解决no session found -->
				<!-- <prop key="hibernate.current_session_context_class">thread</prop> -->
				
				<!-- <prop key="hibernate.cache.use_second_level_cache">true</prop> -->
				<!-- hibernate4的二级缓存配置 -->
				<!-- <prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop> -->
				<!-- hibernate3的二级缓存配置 -->
				<!-- <prop name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop> -->
        		<!-- 开启查询缓存 -->
				<!-- <prop key="hibernate.cache.use_query_cache">true</prop> -->
				
			</props>
		</property>
		<!-- 自动扫描注解方式配置的hibernate类文件 -->
		<property name="packagesToScan">
			<list>
				<value>com.zero4j.model</value>
			</list>
		</property>
		<!-- 手动加载配置映射文件 -->
		<property name="mappingResources">
			<list>
				<!-- <value>com/***/model/order/Order.hbm.xml</value> -->
			</list>
		</property>
		<!-- 手动加载注解类映射文件-->
		<!-- <property name="annotatedClasses">
			<list>
				<value>com.zero4j.model.test.Test</value>
			</list>
		</property> -->
	</bean>

	<!-- 开启注解事务 只对当前配置文件有效 -->
  	<tx:annotation-driven transaction-manager="txManager"/>
	<bean id="txManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
        	<property name="sessionFactory" ref="sessionFactory"/>
   	</bean>

</beans>

5、增加事务管理配置,有两种方式,一种是使用SpringBoot的config注入方式,另外一种是加在hibernate.xml中。(记住下面5.1和5.2是二选一)

5.1、使用SpringBoot的confiug注入方式:增加配置文件TransactionAdviceConfig.java:

package com.isuidian.config;


import org.aspectj.lang.annotation.Aspect;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.interceptor.DefaultTransactionAttribute;
import org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource;
import org.springframework.transaction.interceptor.TransactionInterceptor;

@Aspect
@Configuration
public class TransactionAdviceConfig {

	 //使dao使用session
	private static final String AOP_POINTCUT_EXPRESSION = " (execution(* com..dao..*.*(..))) ";
	//controller由过滤器中进行设置,这里设置会抽风
	/*private static final String AOP_POINTCUT_EXPRESSION2 = " (execution(* com..controller..*.*(..))) ";*/
	 
	 
    @Autowired
    private PlatformTransactionManager transactionManager;

    @Bean
    public TransactionInterceptor txAdvice() {

        DefaultTransactionAttribute txAttr_REQUIRED = new DefaultTransactionAttribute();
        txAttr_REQUIRED.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);

        DefaultTransactionAttribute txAttr_REQUIRED_READONLY = new DefaultTransactionAttribute();
        txAttr_REQUIRED_READONLY.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        txAttr_REQUIRED_READONLY.setReadOnly(true);
        
        
        DefaultTransactionAttribute txAttr_READONLY = new DefaultTransactionAttribute();
        txAttr_READONLY.setReadOnly(true);
        
        

        NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();

        source.addTransactionalMethod("save*", txAttr_REQUIRED);
        source.addTransactionalMethod("add*", txAttr_REQUIRED);
        source.addTransactionalMethod("create*", txAttr_REQUIRED);
        source.addTransactionalMethod("insert*", txAttr_REQUIRED);
        source.addTransactionalMethod("update*", txAttr_REQUIRED);
        source.addTransactionalMethod("merge*", txAttr_REQUIRED);
        source.addTransactionalMethod("del*", txAttr_REQUIRED);
        source.addTransactionalMethod("remove*", txAttr_REQUIRED);
        source.addTransactionalMethod("put*", txAttr_REQUIRED);
        source.addTransactionalMethod("use*", txAttr_REQUIRED);
        source.addTransactionalMethod("exec*", txAttr_REQUIRED);
        source.addTransactionalMethod("set*", txAttr_REQUIRED);
        
        
        source.addTransactionalMethod("get*", txAttr_REQUIRED_READONLY);//特殊,service在save后会重新读取,如果设置成REQUIRED_READONLY,则save不会保存数据
        source.addTransactionalMethod("count*", txAttr_REQUIRED_READONLY);
        source.addTransactionalMethod("find*", txAttr_REQUIRED_READONLY);
        source.addTransactionalMethod("list*", txAttr_REQUIRED_READONLY);
        source.addTransactionalMethod("query*", txAttr_REQUIRED_READONLY);
        source.addTransactionalMethod("find*", txAttr_REQUIRED_READONLY);
        source.addTransactionalMethod("is*", txAttr_REQUIRED_READONLY);
        
        /*
        source.addTransactionalMethod("save*", txAttr_REQUIRED);
        source.addTransactionalMethod("delete*", txAttr_REQUIRED);
        source.addTransactionalMethod("update*", txAttr_REQUIRED);
        source.addTransactionalMethod("exec*", txAttr_REQUIRED);
        source.addTransactionalMethod("set*", txAttr_REQUIRED);
        source.addTransactionalMethod("get*", txAttr_REQUIRED_READONLY);
        source.addTransactionalMethod("query*", txAttr_REQUIRED_READONLY);
        source.addTransactionalMethod("find*", txAttr_REQUIRED_READONLY);
        source.addTransactionalMethod("list*", txAttr_REQUIRED_READONLY);
        source.addTransactionalMethod("count*", txAttr_REQUIRED_READONLY);
        source.addTransactionalMethod("is*", txAttr_REQUIRED_READONLY);
        
        */
        source.addTransactionalMethod("*", txAttr_READONLY);
        return new TransactionInterceptor(transactionManager, source);
    }

    @Bean
    public Advisor txAdviceAdvisor() {
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        pointcut.setExpression( AOP_POINTCUT_EXPRESSION );
        return new DefaultPointcutAdvisor(pointcut, txAdvice());
    }
    
   /* @Bean
    public Advisor txAdviceAdvisor2() {
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        pointcut.setExpression( AOP_POINTCUT_EXPRESSION2 );
        return new DefaultPointcutAdvisor(pointcut, txAdvice());
    }*/
}

5.2、加在hibernate.xml中:

    <tx:advice id="txAdvice" transaction-manager="txManager">
        <tx:attributes>
            <tx:method name="save*" propagation="REQUIRED" />
            <tx:method name="add*" propagation="REQUIRED" />
            <tx:method name="create*" propagation="REQUIRED" />
            <tx:method name="insert*" propagation="REQUIRED" />
            <tx:method name="update*" propagation="REQUIRED" />
            <tx:method name="merge*" propagation="REQUIRED" />
            <tx:method name="del*" propagation="REQUIRED" />
            <tx:method name="remove*" propagation="REQUIRED" />
            <tx:method name="put*" propagation="REQUIRED" />
            <tx:method name="use*" propagation="REQUIRED"/>
            <!--hibernate4必须配置为开启事务 否则 getCurrentSession()获取不到-->
            <tx:method name="get*" propagation="REQUIRED" read-only="true" />
            <tx:method name="count*" propagation="REQUIRED" read-only="true" />
            <tx:method name="find*" propagation="REQUIRED" read-only="true" />
            <tx:method name="list*" propagation="REQUIRED" read-only="true" />
            <tx:method name="*" read-only="true" />
        </tx:attributes>
    </tx:advice>

 

6、增加事务管理过滤器FilterConfig.java,自动开启事务管理:

package com.isuidian.config;


import org.aspectj.lang.annotation.Aspect;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.hibernate5.support.OpenSessionInViewFilter;

@Aspect
@Configuration
public class FilterConfig {

	//解决调用接口时session抽风的问题
	@Bean
	public FilterRegistrationBean<OpenSessionInViewFilter> testFilterRegistration() {	
		FilterRegistrationBean<OpenSessionInViewFilter> registration = new FilterRegistrationBean<>();
		registration.setFilter(new OpenSessionInViewFilter());
		registration.addUrlPatterns("/*");//配置过滤路径
		return registration;
	}
	
}

7、搞掂,启动项目!在需要使用SessionFactory的地方使用如下方式注入即可:

@Autowired
private SessionFactory sessionFactory;

 

常见问题

重复的依赖错误

错误提示如下:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Unsatisfied dependency expressed through method 'entityManagerFactory' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'entityManagerFactoryBuilder' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Unsatisfied dependency expressed through method 'entityManagerFactoryBuilder' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jpaVendorAdapter' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.orm.jpa.JpaVendorAdapter]: Factory method 'jpaVendorAdapter' threw exception; nested exception is java.lang.NoSuchFieldError: HANA
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:769) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:509) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1288) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1127) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:538) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:498) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1083) ~[spring-context-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:853) ~[spring-context-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:546) ~[spring-context-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:142) ~[spring-boot-2.1.1.RELEASE.jar:2.1.1.RELEASE]
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:775) [spring-boot-2.1.1.RELEASE.jar:2.1.1.RELEASE]
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) [spring-boot-2.1.1.RELEASE.jar:2.1.1.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:316) [spring-boot-2.1.1.RELEASE.jar:2.1.1.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1260) [spring-boot-2.1.1.RELEASE.jar:2.1.1.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1248) [spring-boot-2.1.1.RELEASE.jar:2.1.1.RELEASE]
	at com.gushing.GushingApplication.main(GushingApplication.java:29) [classes/:na]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_201]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_201]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_201]
	at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_201]
	at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) [spring-boot-devtools-2.1.1.RELEASE.jar:2.1.1.RELEASE]
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'entityManagerFactoryBuilder' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Unsatisfied dependency expressed through method 'entityManagerFactoryBuilder' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jpaVendorAdapter' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.orm.jpa.JpaVendorAdapter]: Factory method 'jpaVendorAdapter' threw exception; nested exception is java.lang.NoSuchFieldError: HANA
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:769) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:509) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1288) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1127) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:538) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:498) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:273) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1237) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1164) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:857) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:760) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	... 24 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jpaVendorAdapter' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.orm.jpa.JpaVendorAdapter]: Factory method 'jpaVendorAdapter' threw exception; nested exception is java.lang.NoSuchFieldError: HANA
	at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:627) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:456) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1288) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1127) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:538) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:498) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:273) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1237) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1164) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:857) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:760) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	... 38 common frames omitted
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.orm.jpa.JpaVendorAdapter]: Factory method 'jpaVendorAdapter' threw exception; nested exception is java.lang.NoSuchFieldError: HANA
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:622) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	... 52 common frames omitted
Caused by: java.lang.NoSuchFieldError: HANA
	at org.springframework.boot.autoconfigure.orm.jpa.DatabaseLookup.<clinit>(DatabaseLookup.java:56) ~[spring-boot-autoconfigure-2.1.1.RELEASE.jar:2.1.1.RELEASE]
	at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties.determineDatabase(JpaProperties.java:142) ~[spring-boot-autoconfigure-2.1.1.RELEASE.jar:2.1.1.RELEASE]
	at org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.jpaVendorAdapter(JpaBaseConfiguration.java:112) ~[spring-boot-autoconfigure-2.1.1.RELEASE.jar:2.1.1.RELEASE]
	at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaConfiguration$$EnhancerBySpringCGLIB$$f91d7855.CGLIB$jpaVendorAdapter$4(<generated>) ~[spring-boot-autoconfigure-2.1.1.RELEASE.jar:2.1.1.RELEASE]
	at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaConfiguration$$EnhancerBySpringCGLIB$$f91d7855$$FastClassBySpringCGLIB$$292a616.invoke(<generated>) ~[spring-boot-autoconfigure-2.1.1.RELEASE.jar:2.1.1.RELEASE]
	at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244) ~[spring-core-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:363) ~[spring-context-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaConfiguration$$EnhancerBySpringCGLIB$$f91d7855.jpaVendorAdapter(<generated>) ~[spring-boot-autoconfigure-2.1.1.RELEASE.jar:2.1.1.RELEASE]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_201]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_201]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_201]
	at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_201]
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	... 53 common frames omitted

这很有可能你的依赖中有重复的内容,如:

		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-entitymanager</artifactId>
			<version>${hibernate.version}</version>
		</dependency>

这个是需要注释掉的,不然会报错。

在SpringBoot中使用SessionFactory的方法

首先项目中已经使用JPA的方式连接,然后加入hibernate依赖:

	<properties>
		<java.version>1.8</java.version>
		<hibernate.version>5.0.12.Final</hibernate.version>
	</properties>
		<!-- SpringBoot使用Hibernate的SessionFactory -->
		<dependency>
		    <groupId>org.hibernate</groupId>
		    <artifactId>hibernate-core</artifactId>
		    <version>${hibernate.version}</version>
		</dependency>
		<dependency>
		    <groupId>org.hibernate</groupId>
		    <artifactId>hibernate-entitymanager</artifactId>
		    <version>${hibernate.version}</version>
		</dependency>

 

然后有以下几种方式,选择一种合适自己的。

方法一:

增加配置文件HibernateConfig.java:

package com.testSSH.config;

import javax.persistence.EntityManagerFactory;

import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class HibernateConfig {
    
    @Bean
    public SessionFactory sessionFactory(@Qualifier("entityManagerFactory") EntityManagerFactory emf){
         return emf.unwrap(SessionFactory.class);
     }

}

如果要使用@Transactional则需要在application.properties中加上:

spring.jpa.properties.hibernate.current_session_context_class=org.springframework.orm.hibernate5.SpringSessionContext

 

方法二:(推荐)

在SpringBoot的启动类中加上:

	@Bean
	public SessionFactory sessionFactory(HibernateEntityManagerFactory hemf) {
	    return hemf.getSessionFactory();
	}

如果要使用@Transactional则需要在application.properties中加上:

spring.jpa.properties.hibernate.current_session_context_class=org.springframework.orm.hibernate5.SpringSessionContext

 

 

方法三:

在SpringBoot的启动类中加上:

    @Bean
    public HibernateJpaSessionFactoryBean sessionFactory() {
        return new HibernateJpaSessionFactoryBean();
    }

如果要使用@Transactional则需要在application.properties中加上:

spring.jpa.properties.hibernate.current_session_context_class=org.springframework.orm.hibernate5.SpringSessionContext

 

 

使用方法:

@Autowired
private SessionFactory sessionFactory;

 

让SpringBoot2.0不使用hiraki数据库连接池而改用c3p0

SpringBoot2.0默认是用hiraki数据库连接池,听说这个是当今运行效率最高的,但由于某些原因我要使用c3p0数据库连接池,所以就给大家说一下我的配置过程,其实还是挺简单的:

在pom.xml中加上依赖:

		<!-- 不使用默认的hikari数据库连接池,使用c3p0的 -->
		<!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
		<dependency>
		    <groupId>com.mchange</groupId>
		    <artifactId>c3p0</artifactId>
		    <version>0.9.5.4</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/com.mchange/mchange-commons-java -->
		<dependency>
		    <groupId>com.mchange</groupId>
		    <artifactId>mchange-commons-java</artifactId>
		    <version>0.2.15</version>
		</dependency>

然后注释掉原来application.properties中的默认数据库配置而改用c3p0的:

#mysql
#spring.datasource.url=jdbc\:mysql\://localhost\:3306/test?useSSL\=false&characterEncoding\=utf8
#spring.datasource.username=test
#spring.datasource.password=test
#spring.datasource.driver-class-name=com.mysql.jdbc.Driver
#spring.datasource.hikari.minimum-idle=10
#spring.datasource.hikari.maximum-pool-size=50

# c3p0
c3p0.jdbcUrl=jdbc:mysql://localhost:3306/test?autoReconnect=true&amp;autoReconnectForPools=true&amp;useUnicode=true&amp;characterEncoding=utf-8
c3p0.user=test
c3p0.password=test
c3p0.driverClass=com.mysql.jdbc.Driver
#c3p0.minPoolSize=2
#c3p0.maxPoolSize=100
#c3p0.maxIdleTime=0
#c3p0.acquireIncrement=3
#c3p0.maxStatements=1000
#c3p0.initialPoolSize=3
#c3p0.idleConnectionTestPeriod=60
#c3p0.acquireRetryAttempts=30
#c3p0.acquireRetryDelay=1000
#c3p0.breakAfterAcquireFailure=false
#c3p0.testConnectionOnCheckout=false

最后补充配置类:

package com.isuidian.config;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.env.Environment;

@Configuration
public class DataSourceConfiguration {
 
    // c3p0 连接池
    @Bean(name = "dataSource")
    @Qualifier(value = "dataSource")
    @Primary
    @ConfigurationProperties(prefix = "c3p0")
    public DataSource dataSource(@Autowired Environment environment) {
        return DataSourceBuilder.create().type(com.mchange.v2.c3p0.ComboPooledDataSource.class).build();
    }
}

搞掂,部署运行,在springboot的启动信息中可以看到c3p0已经生效了。

SpringBoot2.0+Hibernate在Controller使用Session并发性能调优

从SpringBoot2.0开始,其DataSource就交给了Hikari负责。

对于高并发需求,根据数据库的性能,若然Controller执行时间过长,过多controller正在等待有限的sessionFactory资源,则会造成线程堵塞,引起雪崩。

需要在springboot的配置中假如如下设置:

spring.datasource.hikari.minimum-idle=10
spring.datasource.hikari.maximum-pool-size=50
spring.datasource.hikari.idle-timeout=20000
spring.datasource.hikari.connection-timeout=20000

最主要是maximum-pool-size参数,在不设置的情况下默认是10,所以当用户卡在controller等待使用session资源时,做并发测试的时候就会出现卡死现象,引起雪崩。

如果controller中关于数据查询的部分的执行时间较长,maximum-pool-size一定要调大,但是这个值越大我猜测就越内存,一定要适当。

close