Jpa与Druid线程池及Spring Boot整合(一): spring-boot-starter-data-jpa 搭建持久层


                     


Jpa与Druid线程池及Spring Boot整合(一)

Jpa与Druid线程池及Spring Boot整合(二):几个坑

附录官网文档:core.domain-events域事件

docker实战(一):centos7 yum安装docker

docker实战(二):基础命令篇

docker实战(三):docker网络模式(超详细)

docker实战(四):docker架构原理

docker实战(五):docker镜像及仓库配置

docker实战(六):docker 网络及数据卷设置

docker实战(七):docker 性质及版本选择

认知升维: 道、法、术、器、势


(一)Jpa与Druid连接池及Spring Boot整合作为持久层,遇到系列问题,下面一 一记录:

pom.xml 文件中加入必须的依赖:

<!--设置spring-boot依赖的版本 -->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.6.5</version> <!--2.4.11-->
    <relativePath/>
</parent>


<properties>
   
    <lombok.version>1.18.22</lombok.version>

    <hutool-all.version>5.8.18</hutool-all.version>
    
    <druid.version>1.2.16</druid.version>
 
    <mysql-connector-java.version>8.0.28</mysql-connector-java.version>
    
</properties>

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>${lombok.version}</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>${hutool-all.version}</version>
</dependency>

<!--连接mysql数据库的驱动 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>${mysql-connector-java.version}</version>
</dependency>


<!--阿里巴巴开源的线程池连接框架-->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>${druid.version}</version>
</dependency>

<!-- spring-boot与jpa整合-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 端点监控的配置-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.hateoas</groupId>
    <artifactId>spring-hateoas</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <optional>true</optional>
</dependency>

(二) application.yml配置文件

server:
  port: 9999
  servlet:
    context-path: /
spring: 
 
  #使用JPA作为持久层框架与MYSQL整合---Begin---------------------
  datasource:
    url: jdbc:mysql://localhost:3306/tope-pay-user?&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&useSSL=false
    username: root
    password: 123456
    driverClassName: com.mysql.cj.jdbc.Driver # 8.0意思mysql驱动
    type: com.alibaba.druid.pool.DruidDataSource
    # 初始化大小,最小,最大
    initialSize: 5
    minIdle: 5
    maxActive: 20
    # 配置获取连接等待超时的时间
    maxWait: 60000
    # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
    timeBetweenEvictionRunsMillis: 60000
    # 配置一个连接在池中最小生存的时间,单位是毫秒
    minEvictableIdleTimeMillis: 300000
    validationQuery: SELECT 1 FROM DUAL
    testWhileIdle: true
    testOnBorrow: false

    testOnReturn: false
    # 打开PSCache,并且指定每个连接上PSCache的大小
    poolPreparedStatements: true
    maxPoolPreparedStatementPerConnectionSize: 20
    # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
    filters: stat,wall,log4j
    # 通过connectProperties属性来打开mergeSql功能;慢SQL记录
    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
    # 合并多个DruidDataSource的监控数据
    #spring.datasource.useGlobalDataSourceStat=true

  jpa:
    properties:
      hibernate:
        dialect: org.hibernate.dialect.MySQL5Dialect # stripped before adding them to the entity manager)
    database: MYSQL
    show-sql: true # 打印执行的SQL
    hibernate:
      ddl-auto: update   # Hibernate ddl auto (create, create-drop, update, validate, none)
      naming:
        implicit-strategy: org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
      naming-strategy: org.hibernate.cfg.ImprovedNamingStrategy
      #使用JPA作为持久层框架与MYSQL整合---end---------------------

编写Druid(alibaba数据库连接池)初始化配置:


package org.jd.websocket.auth.data.reactor.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.*;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import java.sql.SQLException;

/**
 * @Transactiona在多数据源下失效
 * 在多数据源的情况下,如果transactionManager进行了分开配置,比如这里针对三个数据源配置了三个transactionManager
 * ===========================================================================================================
 * @Bean("formTransactionManager")
 * public PlatformTransactionManager transactionManager(EntityManagerFactoryBuilder builder) {
 *     return new JpaTransactionManager(Objects.requireNonNull(entityManagerFactory(builder).getObject()));
 * }
 *=============================================================================================================
 * @Bean("fileTransactionManager")
 * public PlatformTransactionManager transactionManager(EntityManagerFactoryBuilder builder) {
 *     return new JpaTransactionManager(Objects.requireNonNull(entityManagerFactory(builder).getObject()));
 * }
 * ============================================================================================================
 * @Primary
 * @Bean("userTransactionManager")
 * public PlatformTransactionManager transactionManager(EntityManagerFactoryBuilder builder) {
 *     return new JpaTransactionManager(Objects.requireNonNull(entityManagerFactory(builder).getObject()));
 * }
 * =============================================================================================================
 *
 * 那么在使用@Transactional的时候需要指定transactionManager
 * @Transactional("formTransactionManager")
 *
 *
 *
 *
 *
 *
 * Jpa与Druid线程池整合作为持久层
 */
@Configuration
@EntityScan(basePackages = "org.jd.websocket.auth.data.reactor.jpa")
@EnableTransactionManagement // 开启事务的支持
@EnableJpaRepositories(basePackages = {"org.jd.websocket.auth.data.reactor.repository","org.jd.websocket.auth.data.reactor.jpa"},
        includeFilters = {@ComponentScan.Filter(type = FilterType.REGEX, pattern = ".*CrudRepository")},
        excludeFilters = {@ComponentScan.Filter(type = FilterType.REGEX, pattern = ".*SomeOtherRepository")})
public class JpaDruidConfig {
    @Value("${spring.datasource.url}")
    private String dbUrl;

    @Value("${spring.datasource.username}")
    private String username;
    @Value("${spring.datasource.password}")
    private String password;
    @Value("${spring.datasource.driver-class-name}")
    private String driverClassName;

    @Value("${spring.datasource.initialSize}")
    private int initialSize;
    @Value("${spring.datasource.minIdle}")
    private int minIdle;
    @Value("${spring.datasource.maxActive}")
    private int maxActive;
    @Value("${spring.datasource.maxWait}")
    private int maxWait;
    @Value("${spring.datasource.timeBetweenEvictionRunsMillis}")
    private int timeBetweenEvictionRunsMillis;
    @Value("${spring.datasource.minEvictableIdleTimeMillis}")
    private int minEvictableIdleTimeMillis;
    @Value("${spring.datasource.validationQuery}")
    private String validationQuery;
    @Value("${spring.datasource.testWhileIdle}")
    private boolean testWhileIdle;
    @Value("${spring.datasource.testOnBorrow}")
    private boolean testOnBorrow;
    @Value("${spring.datasource.testOnReturn}")
    private boolean testOnReturn;
    @Value("${spring.datasource.poolPreparedStatements}")
    private boolean poolPreparedStatements;
    @Value("${spring.datasource.maxPoolPreparedStatementPerConnectionSize}")
    private int maxPoolPreparedStatementPerConnectionSize;
    @Value("${spring.datasource.filters}")
    private String filters;
    @Value("{spring.datasource.connectionProperties}")
    private String connectionProperties;

    @Bean
    @Primary
    public DataSource dataSource() {
        DruidDataSource datasource = new DruidDataSource();
        datasource.setUrl(dbUrl);
        datasource.setUsername(username);
        datasource.setPassword(password);
        datasource.setDriverClassName(driverClassName);
        // configuration
        datasource.setInitialSize(initialSize);
        datasource.setMinIdle(minIdle);
        datasource.setMaxActive(maxActive);
        datasource.setMaxWait(maxWait);
        datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
        datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
        datasource.setValidationQuery(validationQuery);
        datasource.setTestWhileIdle(testWhileIdle);
        datasource.setTestOnBorrow(testOnBorrow);
        datasource.setTestOnReturn(testOnReturn);
        datasource.setPoolPreparedStatements(poolPreparedStatements);
        datasource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
        try {
            datasource.setFilters(filters);
        } catch (SQLException e) {
            System.err.println("druid configuration initialization filter: " + e);
        }
        datasource.setConnectionProperties(connectionProperties);
        return datasource;
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        vendorAdapter.setGenerateDdl(true);
        LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
        factory.setJpaVendorAdapter(vendorAdapter);
        // entity扫描的包路径
        factory.setPackagesToScan("org.jd.websocket.auth.data.reactor.jpa");
        factory.setDataSource(dataSource());
        return factory;
    }

    /**
     *
     * @param entityManagerFactory
     * @return
     */
    @Primary
    @Bean(name = "userJpaTransactionManager")
    public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
        JpaTransactionManager txManager = new JpaTransactionManager();
        txManager.setEntityManagerFactory(entityManagerFactory);
        return txManager;
    }

    @Bean
    public ServletRegistrationBean statViewServlet() {
        System.out.print("init Druid Monitor Servlet ...");
        ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
        servletRegistrationBean.addInitParameter("allow", "127.0.0.1");
        // IP黑名单(共同存在时,deny优先于allow)
        servletRegistrationBean.addInitParameter("deny", "192.168.1.100");
        //控制台管理用户
        servletRegistrationBean.addInitParameter("loginUsername", "admin");
        servletRegistrationBean.addInitParameter("loginPassword", "123456");
        servletRegistrationBean.addInitParameter("resetEnable", "false");
        System.out.print("注册成功");
        return servletRegistrationBean;
    }

    @Bean
    public FilterRegistrationBean startFilter() {
        FilterRegistrationBean filterRegistrationBean =
                new FilterRegistrationBean(new WebStatFilter());
        filterRegistrationBean.addUrlPatterns("/*");
        // 忽略过滤的格式
        filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
        return filterRegistrationBean;
    }

}

启动报错:

init Druid Monitor Servlet ...注册成功2023-08-10 21:03:14.026  INFO 10256 --- [  restartedMain] c.github.jasync.sql.db.util.NettyUtils   : jasync selected transport - nio
2023-08-10 21:03:14.221  WARN 10256 --- [  restartedMain] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaConfiguration': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [org/jd/websocket/auth/data/reactor/config/JpaDruidConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.sql.DataSource]: Factory method 'dataSource' threw exception; nested exception is java.lang.NoClassDefFoundError: org/apache/log4j/Logger
2023-08-10 21:03:14.233  INFO 10256 --- [  restartedMain] o.apache.catalina.core.StandardService   : Stopping service [Tomcat]
2023-08-10 21:03:14.271  INFO 10256 --- [  restartedMain] ConditionEvaluationReportLoggingListener : 

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2023-08-10 21:03:14.331 ERROR 10256 --- [  restartedMain] o.s.boot.SpringApplication               : Application run failed


Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [org/jd/websocket/auth/data/reactor/config/JpaDruidConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.sql.DataSource]: Factory method 'dataSource' threw exception; nested exception is java.lang.NoClassDefFoundError: org/apache/log4j/Logger

    ... 33 common frames omitted
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.sql.DataSource]: Factory method 'dataSource' threw exception; nested exception is java.lang.NoClassDefFoundError: org/apache/log4j/Logger
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185) ~[spring-beans-5.3.17.jar:5.3.17]
    at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:653) ~[spring-beans-5.3.17.jar:5.3.17]
    ... 47 common frames omitted
Caused by: java.lang.NoClassDefFoundError: org/apache/log4j/Logger
    at com.alibaba.druid.filter.logging.Log4jFilter.<init>(Log4jFilter.java:25) ~[druid-1.2.16.jar:na]
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.8.0_221]
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:1.8.0_221]
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:1.8.0_221]
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423) ~[na:1.8.0_221]

 java.lang.NoClassDefFoundError: org/apache/log4j/Logger 报错最终信息

 问题一: 缺少,Druid初始化化依赖 org/apache/log4j/Logger;但是不应该呀,Spring-Boot不是已经添加了该依赖吗,百思不得其解....于是翻下相应包是否依赖,如下图,都没引入该包的依赖....

 引入Logger三角坐标:


<!-- spring-boot与jpa整合,当前者版本依赖这个,需要加上,否则启动不了-->
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

再次启动项目: 可以正常启动但是有个警告:

log4j:WARN No appenders could be found for logger (druid.sql.Connection).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.

 很明显druid启动过程会加载日志配置文件. 在resources目录下面新建"log4j.properties"文件,内容如下,启动就正常了;

log4j.rootLogger=INFO,toFile,toConsole  
########   输出到到文件   ##########
log4j.appender.toFile=org.apache.log4j.FileAppender  
log4j.appender.toFile.layout=org.apache.log4j.PatternLayout  
log4j.appender.toFile.file=test.log  
########  输出到到控制台  ##########
log4j.appender.toConsole=org.apache.log4j.ConsoleAppender  
log4j.appender.toConsole.layout=org.apache.log4j.PatternLayout 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值