顺顺博客分享快乐,分享知识。
Spring Boot中JPA多数据源配置案例——基础演示
21-02-23 17:39:49首页1089

JPA 在 Spring Boot中和MyBatis配置多数据源大多都很相似,

而JPA主要提供与MyBatis不同的是LocalContainerEntityManagerFactoryBean与事务管理器

本案例使用基于最新版2.2.6.RELEASE(貌似最近个把月出来的)+ mysql(上面图很清楚)

大多详细内容介绍写在注解里,案例源码在文章后

#1. 准备工作

添加基础依赖(注意下使用的是druid-spring-boot-starter而不是单单是druid)

mysql mysql-connector-java runtime org.springframework.boot spring-boot-starter-data-jpa com.alibaba druid-spring-boot-starter 1.1.20 org.springframework.boot spring-boot-starter-web
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
        <exclusions>
            <exclusion>
                <groupId>org.junit.vintage</groupId>
                <artifactId>junit-vintage-engine</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

建库no1与no2(使用的是MySql):

create database no1 default character set utf8; use no1; create table customer ( id int(12) not null auto_increment, name varchar(56) default null, gender char(2) default null, age tinyint(100) default null, email varchar(128) default null, primary key (id) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

create database no2; use no2; create table customer ( id int(12) not null auto_increment, name varchar(56) default null, gender char(2) default null, age tinyint(100) default null, email varchar(128) default null, primary key (id) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

然后配置application.properties

数据源 1

spring.datasource.no1.type=com.alibaba.druid.pool.DruidDataSource spring.datasource.no1.username=** spring.datasource.no1.password=***** spring.datasource.no1.url=jdbc:mysql://**/no1

数据源 2

spring.datasource.no2.type=com.alibaba.druid.pool.DruidDataSource spring.datasource.no2.username=** spring.datasource.no2.password=*** spring.datasource.no2.url=jdbc:mysql://**/no2 #与单独的JPA有所区别,因为后面在JpaProperties中getProperties 方法获取所有JPA的相关配置 #所以属性前缀都是spring.jpa.properties spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL57InnoDBDialect #在配置spring data jpa时,如果spring.jpa.properties.hibernate.hbm2ddl.auto设置为update,

会自动更新数据表结构,比如Entity中增加成员变量,数据表中也会增加相应的字段,但是需要注意的是,如果删除一个成员变量,

这时数据表中不会自动删除对应的字段,如果删除的那个成员变量在数据表中被设置为not null

spring.jpa.properties.database=mysql spring.jpa.properties.hibernate.hbm2ddl.auto=update spring.jpa.properties.show-sql=true #2.实体类Customer

package com.slt6.model;

import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id;

@Entity(name = "customer") public class Customer { @Id //@GeneratedValue表示主键自动生成,strategy表示生成主键的策略 @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; private String name; private String gender; private Integer age; private String email;

@Override
public String toString() {
    return "Customer{" +
            "id=" + id +
            ", name='" + name + '\'' +
            ", gender='" + gender + '\'' +
            ", age=" + age +
            ", email='" + email + '\'' +
            '}';
}

public Integer getId() {
    return id;
}

public void setId(Integer id) {
    this.id = id;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public String getGender() {
    return gender;
}

public void setGender(String gender) {
    this.gender = gender;
}

public Integer getAge() {
    return age;
}

public void setAge(Integer age) {
    this.age = age;
}

public String getEmail() {
    return email;
}

public void setEmail(String email) {
    this.email = email;
}

}

#3. 创建Repository(CustomerDao1与CustomerDao2)

//自定义CustomerDao1继承自JpaRepository public interface CustomerDao1 extends JpaRepository<Customer,Integer> { List getCustomersByNameStartingWith(String name); List getCustomersByAgeGreaterThan(Integer age); @Query(value = "select * from customer where age = (select max(age) from customer)",nativeQuery = true)//nativeQuery表示使用原生的SQL查询 Customer getMaxIdCustomer(); //利用:name这种方式进行命名绑定 @Query("select email from customer where name=:name") String getCustomerByName(@Param("name") String name); }

public interface CustomerDao2 extends JpaRepository<Customer,Integer> { List getCustomersByNameStartingWith(String name); List getCustomersByAgeGreaterThan(Integer age); @Query(value = "select * from customer where age = (select max(age) from customer)",nativeQuery = true)//nativeQuery表示使用原生的SQL查询 Customer getMaxIdCustomer(); //利用?1这种方式进行命名绑定 @Query("select email from customer where name=?1") String getCustomerByName(String name); }

#4. Config配置环节

创建DatasourceConfig配置

Spring Boot还可以根据我们使用的数据库自动配置dataSource bean。

对于类型为H2,HSQLDB和Apache、Derby的内存数据库,如果该类中

存在相应的数据库依赖关系,则Spring Boot会自动配置DataSource

@Configuration public class DataSourceConfig { @Bean //@ConfigurationProperties注解表示使用不同前缀的配置文件来创建不同的Datasource实例 @ConfigurationProperties("spring.datasource.no1") //@Primary优选 @Primary DataSource dsNo1(){ return DruidDataSourceBuilder.create().build(); } @Bean @ConfigurationProperties("spring.datasource.no2") DataSource dsNo2(){ return DruidDataSourceBuilder.create().build(); } }

创建JPA配置(总共两个JpaConfigNo1和JpaConfigNo2

@Configuration //开启实事务管理器 @EnableTransactionManagement //@EnableJpaRepositories注解进行JPA配置 //basePackages用来指定Repository所在的位置 //entityManagerFactoryRef用来指定实体类管理工厂Bean的名称 //transactionmanagerRef则用来指定事务管理器的引用名称,这里引用的名称是JpaConfigNo1类中注册的Bean的名称 @EnableJpaRepositories(basePackages = "com.slt6.dao1",entityManagerFactoryRef = "entityManagerFactoryBeanNo1",transactionManagerRef = "platformTransactionManagerNo1") public class JpaConfigNo1 { @Resource(name = "dsNo1") DataSource dsNo1; @Autowired //获取所有JPA的相关配置 JpaProperties jpaProperties; @Bean //因为有两个所以这个优选 @Primary //该Bean用来提供EntityManager实例 LocalContainerEntityManagerFactoryBean entityManagerFactoryBeanNo1(EntityManagerFactoryBuilder builder){ return builder.dataSource(dsNo1) //配置数据源 .properties(jpaProperties.getProperties()) //设置JPA相关配置,系统自动加载 .packages("com.slt6.model") //设置实体类所在位置 .persistenceUnit("pu1") //配置持久化单元名(注:项目中只有一个EntityManagerFactory,则可以忽略,多个必须设置) .build(); } @Bean PlatformTransactionManager platformTransactionManagerNo1(EntityManagerFactoryBuilder builder){ LocalContainerEntityManagerFactoryBean factoryNo1 = entityManagerFactoryBeanNo1(builder); //对单个EntityManagerFactory的事务支持,解决JPA中的事务管理 return new JpaTransactionManager(factoryNo1.getObject()); } } //第二个 @Configuration @EnableTransactionManagement @EnableJpaRepositories(basePackages = "com.slt6.dao2",entityManagerFactoryRef = "entityManagerFactoryBeanNo2",transactionManagerRef = "platformTransactionManagerNo2") public class JpaConfigNo2 { @Resource(name = "dsNo2") DataSource dsNo2; @Autowired JpaProperties jpaProperties; @Bean LocalContainerEntityManagerFactoryBean entityManagerFactoryBeanNo2(EntityManagerFactoryBuilder builder){ return builder.dataSource(dsNo2) .properties(jpaProperties.getProperties()) .packages("com.slt6.model") .persistenceUnit("pu2") .build(); } @Bean PlatformTransactionManager platformTransactionManagerNo2(EntityManagerFactoryBuilder builder){ LocalContainerEntityManagerFactoryBean factoryNo2 = entityManagerFactoryBeanNo2(builder); return new JpaTransactionManager(factoryNo2.getObject()); } }

#5. 创建Service层Service1和Service2

@Service public class Service1 { @Autowired CustomerDao1 customerDao1; //与Dao基本依依对应 public void addCustomer(Customer customer){ customerDao1.save(customer); } public List getCustomersByNameStartingWith(String name){ return customerDao1.getCustomersByNameStartingWith(name); } public List getCustomersByAgeGreaterThan(int age){ return customerDao1.getCustomersByAgeGreaterThan(age); } public Customer getMaxIdCustomer(){ return customerDao1.getMaxIdCustomer(); } public String getCustomerByName(String name){ return customerDao1.getCustomerByName(name); } } //第二个 @Service public class Service2 { @Autowired CustomerDao2 customerDao2; public void addCustomer(Customer customer){ customerDao2.save(customer); } public List getCustomersByNameStartingWith(String name){ return customerDao2.getCustomersByNameStartingWith(name); } public List getCustomersByAgeGreaterThan(int age){ return customerDao2.getCustomersByAgeGreaterThan(age); } public Customer getMaxIdCustomer(){ return customerDao2.getMaxIdCustomer(); } public String getCustomerByName(String name){ return customerDao2.getCustomerByName(name); } }

#6. 创建Controller

@RestController public class CustomerController { @Autowired Service1 service1; @Autowired Service2 service2; //先执行保存(/save)再执行/p @GetMapping("/save") public void save(){ Customer customer1 = new Customer(); customer1.setName("顺子"); customer1.setAge(20); customer1.setGender("男"); customer1.setEmail("snet@shunleite.com"); Customer customer2 = new Customer(); customer2.setName("老王"); customer2.setAge(55); customer2.setGender("女"); customer2.setEmail("123456@example.com"); service1.addCustomer(customer1); service1.addCustomer(customer2); service2.addCustomer(customer2); service2.addCustomer(customer1); } @GetMapping("/q") public void p(){ Customer ld = service1.getMaxIdCustomer(); List l1 = service1.getCustomersByAgeGreaterThan(20); List l2 = service1.getCustomersByNameStartingWith("顺"); String l3 = service1.getCustomerByName("老王"); Customer zd = service2.getMaxIdCustomer(); List z1 = service2.getCustomersByAgeGreaterThan(20); List z2 = service2.getCustomersByNameStartingWith("老"); String z3 = service2.getCustomerByName("顺子"); System.out.println("第一个数据库:"); System.out.println("ld:" + ld); System.out.println("l1:" + l1); System.out.println("l2:" + l2); System.out.println("l3:" + l3); System.out.println("第二个数据库:"); System.out.println("zd:" + zd); System.out.println("z1:" + z1); System.out.println("z2:" + z2); System.out.println("z3:" + z3); } } 运行的效果

下载慢,请在我的Box工具中粘贴下载的连接可起到加速下载的效果