在spring boot项目中使用Spring Boot Jpa 通过Druid配置多数据源、文章末尾对比Hakari连接池。

Spring Boot Jpa 介绍

首先了解 Jpa 是什么?

Jpa (Java Persistence API) 是 Sun 官方提出的 Java 持久化规范。它为 Java 开发人员提供了一种对象/关联映射工具来管理 Java 应用中的关系数据。它的出现主要是为了简化现有的持久化开发工作和整合 ORM 技术,结束现在 Hibernate,TopLink,JDO 等 ORM 框架各自为营的局面。

值得注意的是,Jpa是在充分吸收了现有 Hibernate,TopLink,JDO 等 ORM 框架的基础上发展而来的,具有易于使用,伸缩性强等优点。从目前的开发社区的反应上看,Jpa 受到了极大的支持和赞扬,其中就包括了 Spring 与 EJB3. 0的开发团队。

注意:Jpa 是一套规范,不是一套产品,那么像 Hibernate,TopLink,JDO 他们是一套产品,如果说这些产品实现了这个 Jpa 规范,那么我们就可以叫他们为 Jpa 的实现产品。

Spring Boot Jpa

Spring Boot Jpa 是 Spring 基于 ORM 框架、Jpa 规范的基础上封装的一套 Jpa 应用框架,可使开发者用极简的代码即可实现对数据的访问和操作。它提供了包括增删改查等在内的常用功能,且易于扩展!学习并使用 Spring Data Jpa 可以极大提高开发效率!

Spring Boot Jpa 让我们解脱了 DAO 层的操作,基本上所有 CRUD 都可以依赖于它来实现

基本查询

基本查询也分为两种,一种是 Spring Data 默认已经实现,一种是根据查询的方法来自动解析成 SQL。

预先生成方法

Spring Boot Jpa 默认预先生成了一些基本的CURD的方法,例如:增、删、改等等

继承 JpaRepository

public interface UserRepository extends JpaRepository {
}

一 我们使用首先要引入spring data jpa 的jar包 

       
            org.springframework.boot
            spring-boot-starter-data-jpa
            
                
                    org.slf4j
                    jcl-over-slf4j
                
            
        

也要引入druid的jar包

        
            com.alibaba
            druid
            1.1.10
        

二、要在 application.properties 配置文件中配置两个数据源的一些信息

#first datasource
spring.datasource.first.url=jdbc:oracle:thin:@//ip1:1521/ORCL
spring.datasource.first.username=name1
spring.datasource.first.password=password1
spring.datasource.first.driverClassName=oracle.jdbc.driver.OracleDriver
spring.datasource.first.test-while-idle=true
spring.datasource.first.test-on-borrow=false
spring.datasource.first.test-on-return=false
spring.datasource.first.validation-query=SELECT 1 FROM DUAL
spring.datasource.first.time-between-eviction-runs-millis=300000
spring.datasource.first.min-evictable-idle-time-millis=1800000
spring.datasource.first.initial-size=5
spring.datasource.first.max-active=50
spring.datasource.first.max-wait=60000
spring.datasource.first.min-idle=5


#second datasource
spring.datasource.second.url=jdbc:oracle:thin:@//ip2:1521/ORCL
spring.datasource.second.username=name2
spring.datasource.second.password=password2
spring.datasource.second.driverClassName=oracle.jdbc.driver.OracleDriver
spring.datasource.second.test-while-idle=true
spring.datasource.second.test-on-borrow=false
spring.datasource.second.test-on-return=false
spring.datasource.second.validation-query=SELECT 1 FROM DUAL
spring.datasource.second.time-between-eviction-runs-millis=300000
spring.datasource.second.min-evictable-idle-time-millis=1800000
spring.datasource.second.initial-size=5
spring.datasource.second.max-active=50
spring.datasource.second.max-wait=60000
spring.datasource.second.min-idle=5

三、开始配置第一数据源也就是第一数据源也就是主数据源

1、配置dataSource的FirstDataSourceConfig类

import javax.sql.DataSource;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;


@Configuration
public class FirstDataSourceConfig {

    @Bean(name = {"firstDataSource"})
    @Qualifier("firstDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.first")
    @Primary
    public DataSource firstDataSource() {
        return DataSourceBuilder.create().type(com.alibaba.druid.pool.DruidDataSource.class).build();
    }

   /* public DruidDataSource firstDataSource(){
        return new DruidDataSource();
    }*/


    @Bean(name = {"jdbcTemplateDmdb"})
    @Primary
    public JdbcTemplate jdbcTemplate(@Qualifier("firstDataSource") DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }


}

2、配置jpa的 repository文件


import java.util.Map;
import javax.persistence.EntityManager;
import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;


@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "entityManagerFactoryFirst",
        transactionManagerRef = "transactionManagerFirst",
        basePackages = {"cn.com.repository"}) //repository所在包的位置
public class RepositoryFirstConfig {

    @Autowired
    private JpaProperties jpaProperties;

    @Autowired
    @Qualifier("firstDataSource")
    private DataSource firstDS;

    @Bean(name = "entityManagerFirst")
    @Primary
    public EntityManager entityManagerFirst(EntityManagerFactoryBuilder builder) {
        return entityManagerFactorySecondary(builder).getObject().createEntityManager();
    }

    @Bean(name = "entityManagerFactoryFirst")
    @Primary
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryFirst(EntityManagerFactoryBuilder builder) {
        return builder
                .dataSource(firstDS)
                .properties(getVendorProperties(firstDS))
                .packages("cn.com.domain")   //domain所在包的位置
                .persistenceUnit("firstPersistenceUnit")
                .build();
    }

    private Map getVendorProperties(DataSource dataSource) {
        return jpaProperties.getHibernateProperties(dataSource);
    }

    @Bean(name = "transactionManagerFirst")
    @Primary
    PlatformTransactionManager transactionManagerFirst(EntityManagerFactoryBuilder builder) {
        return new JpaTransactionManager(entityManagerFactoryFirst(builder).getObject());
    }
}

四、配置第二数据源信息

1、配置dataSource的SecondDataSourceConfig类

import javax.sql.DataSource;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;


@Configuration
public class SecondDataSourceConfig {

    @Bean(name = {"secondaryDataSource"})
    @Qualifier("secondaryDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.second")
    public DataSource secondaryDataSource() {
        return DataSourceBuilder.create().type(com.alibaba.druid.pool.DruidDataSource.class).build();
    }

   /* public DruidDataSource secondaryDataSource(){
        return new DruidDataSource();
    }*/


    @Bean(name = {"jdbcTemplateDmdb"})
    public JdbcTemplate jdbcTemplate(@Qualifier("secondaryDataSource") DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }


}

2、配置jpa的 repository文件


import java.util.Map;
import javax.persistence.EntityManager;
import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;


@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "entityManagerFactorySecondary",
        transactionManagerRef = "transactionManagerSecondary",
        basePackages = {"cn.com.repository2"}) //repository所在包的位置
public class RepositorySecondaryConfig {

    @Autowired
    private JpaProperties jpaProperties;

    @Autowired
    @Qualifier("secondaryDataSource")
    private DataSource secondaryDS;

    @Bean(name = "entityManagerSecondary")
    public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
        return entityManagerFactorySecondary(builder).getObject().createEntityManager();
    }

    @Bean(name = "entityManagerFactorySecondary")
    public LocalContainerEntityManagerFactoryBean entityManagerFactorySecondary(EntityManagerFactoryBuilder builder) {
        return builder
                .dataSource(secondaryDS)
                .properties(getVendorProperties(secondaryDS))
                .packages("cn.com.domain2")   //domain所在包的位置
                .persistenceUnit("secondaryPersistenceUnit")
                .build();
    }

    private Map getVendorProperties(DataSource dataSource) {
        return jpaProperties.getHibernateProperties(dataSource);
    }

    @Bean(name = "transactionManagerSecondary")
    PlatformTransactionManager transactionManagerSecondary(EntityManagerFactoryBuilder builder) {
        return new JpaTransactionManager(entityManagerFactorySecondary(builder).getObject());
    }
}

五、到此多数据源已经都配置好了,如果需要配置更多数据源以此类推。需要注意的是spring boot jpa 的repository文件配置扫描的包要配置好(repository所在包的位置、domain所在包的位置),不然的话这个数据源在你想要的的作用域是不起作用的。

六、如果我想直接用hibernate的sessionFactory原生的语句查询

1、首先配置hibernate的session新建一个类在需要的类继续此类就行

package cn.com.xxx.common;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;


public abstract class MyHibernateDaoSupport {
    private static final Logger log = LoggerFactory.getLogger(MyHibernateDaoSupport.class);

    private Session session;
    @Autowired
    private SessionFactory sessionFactory;

    private void startOperation() {
        try {
            session = sessionFactory.openSession();
        } catch (Exception e) {
            log.error("获取 Hibernate Session 异常", e);
        }
    }

    protected void closeSession() {
        if (session != null) {
            try {
                session.close();
            } catch (Exception e) {
                log.error("关闭 Hibernate Session 异常", e);
            }
        }
    }

    protected Session getSession() throws HibernateException {
        if (this.session == null || !this.session.isOpen()) {
            startOperation();
        }

        return session;
    }

}

2、springboot配置加载sessionFactory的数据源、咱们已第二数据源为列新建一个配置类

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

import javax.persistence.EntityManagerFactory;

@Configuration
public class HibernateConfig {

    /**
     * entityManagerFactorySecondary 要选择第二数据源的entityManagerFactory
     * @param emf
     * @return
     */
    @Bean
    public SessionFactory sessionFactory(@Qualifier("entityManagerFactorySecondary") EntityManagerFactory emf) {
        return emf.unwrap(SessionFactory.class);
    }


}

3、直接就可以在类中使用session来sql语句操作了

public class DataServiceImpl extends MyHibernateDaoSupport{
  @Override
    public void getClassDropDown() {
        try {
            Map map = new HashMap();
            List arrayList = new ArrayList();
            String sql = "SELECT FLDNAME FROM TABLENAME WHERE FLDNAME IS NOT 
             NULL GROUP BY FLDNAME ";
            SQLQuery sqlQuery = getSession().createSQLQuery(sql);
            List listObj = sqlQuery.list();
        } catch (Exception e) {
            log.error("异常" + e);
        } finally {
            closeSession();
        }
    }

}

现在很多druid数据库连接池但是我在网上看到的性能问题是Hakari要比druid好很多,我也没验证过不知道真假在此看到一个网友关于Hakari配置多数据的拿来和Druid多数据源配置对比一下。springBoot1.x版本的数据库连接池不是Hakari,在springBoot2.0版本以后才默认是Hakari。文章链接

你可能感兴趣的:(java开发的点点滴滴)