springboot整合springdata jpa 与多数据源

2023-11-11 09:41

本文主要是介绍springboot整合springdata jpa 与多数据源,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

springboot整合springdata jpa 与多数据源

1.整合springdata jpa

1.建库

新建一个数据库 命名为 jpa

不用建表,我们通过构建实体类来自动生成表

2.引入依赖

(默认是web项目,以提前引入了web和thymeleaf的starter)

          <dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.9</version></dependency>

3.数据库配置

spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.url=jdbc:mysql:///jpa?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=123
#以上数据库的基本信息
spring.jpa.show-sql=true
#开启控制台打印生成sql过程
spring.jpa.database=mysql
#项目启动时根据实体类的值自动更新数据库中的表,可选有create,create-drop,validate,no
spring.jpa.hibernate.ddl-auto=update
#规定使用数据库的官方语言是MySQL57Dialect
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL57Dialect

4.entity层

@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity(name = "t_book")
public class Book {@Id@GeneratedValue(strategy = GenerationType.AUTO)private Integer id;@Column(name = "book_name", nullable = false)private String bookName;private String author;private Float price;
//@Transient 代表生成表时,不生成此字段@Transientprivate String description;
}

5.dao层

public interface BookDao extends JpaRepository<Book, Integer> {//    根据作者名字获取书的集合List<Book> getBooksByAuthorStartingWith(String author);//  根据提供价格大于的获取书的集合List<Book> getBooksByPriceGreaterThan(Float price);//获取编号最大的书 ,nativeQuery 开启原生sql@Query(value = "select * from t_book where id=(select max(id) from t_book)", nativeQuery = true)Book getMaxIdBook();//    :id ,:author 用来做参数绑定,这里使用的的列名是属性名 不是数据库中列的名字//采用此种方式,一定要写 @param@Query("select b from t_book b where b.id>:id and b.author=:author")List<Book> getBookByIdAndAuthor(@Param("author") String author, @Param("id") Integer id);//?1 ,?2是另一种参数声明方式,但要注意参数的顺序@Query("select b from t_book b where b.id<?2 and b.bookName like %?1%")List<Book> getBooksByIdAndName(String name, Integer id);//    对于update操作,需要添加@Modifying注解并添事务(可以在service实现层方法上加上 @Transactional(isolation = Isolation.READ_COMMITTED))@Modifying@Query(value = "update t_book b set b.book_name=:newName where b.id =:id", nativeQuery = true)void updateBookName(@Param("newName") String newName,@Param("id") Integer id);}

1.使用springdata jpa ,编写dao层使,我们可以直接继承 JpaRepository<实体类class ,主键类型> ,其中提供了一些基本的增删改善,分页查询,排序查询等

2.在springdata jpa中,只要方法的名字符合既定规范,springdata就能分析出你的意图,从而可以避免自己定义sql.也就是根据方法名字自动生成sql语句。我们可以在ecplice或idea中开启方法提示功能,那么输入find 或get 就会有很多的提示方法。当然我们也可以去看官方文档的命名规则,这里我们就不陈述了。

3.如果既定规范不能满足要求,那么 可以采用编写原生sql的方法。例如第10行代码,加上 nativeQuery = true

,就支持原生sql了。

4.传递参数 有两个方式,在上述代码中已经写明。

5.对于修改操作,需要添加@Modifying注解并添事务(可以在service实现层方法上加上 @Transactional(isolation = Isolation.READ_COMMITTED))。

6.service层

@Service
public class BookService {@AutowiredBookDao bookDao;public void addBook(Book book) {bookDao.save(book);}public Page<Book> getBookByPage(Pageable pageable) {return bookDao.findAll(pageable);}public List<Book> getBooksByAuthorStartingWith(String author) {return bookDao.getBooksByAuthorStartingWith(author);}public List<Book> getBooksByPriceGreaterThan(Float price) {return bookDao.getBooksByPriceGreaterThan(price);}public Book getMaxIdBook() {return bookDao.getMaxIdBook();}public List<Book> getBookByIdAndAuthor(String author, Integer id) {return bookDao.getBookByIdAndAuthor(author, id);}public List<Book> getBooksByIdAndName(String name, Integer id) {return bookDao.getBooksByIdAndName(name, id);}@Transactional(isolation = Isolation.READ_COMMITTED)public  void  updateBookName(String newName,Integer id){bookDao.updateBookName(newName,id);}

7.controller层

@RestController
public class BookController {@AutowiredBookService bookService;@GetMapping("/findAll")public void findAll() {
//        首先通过PageRequest.of方法获得一个PageRequest对象,arm1 代表第几页(从0开始),arm2代码每页显示的条数PageRequest pageable = PageRequest.of(1, 3);Page<Book> page = bookService.getBookByPage(pageable);System.out.println("总页数:" + page.getTotalPages());System.out.println("总记录数:" + page.getTotalElements());System.out.println("查询结果:" + page.getContent());System.out.println("当前页数:" + (page.getNumber() + 1));System.out.println("当前页记录数:" + page.getNumberOfElements());System.out.println("每页记录数:" + page.getSize());}
}

这里只做一个对分页查询的方法。数据库数据可以自己添加。

2.Jpa多数据源

1.建库

新建两个数据库 muljpa1muljpa2,不用建表,我们通过构建实体类来自动生成表.

2.引入依赖

依赖与上面差不多,只需要改变一个druid的依赖

        <dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.1.10</version></dependency>

3,数据库连接和jpa相关配置

配置两个数据源,区别主要是数据库不同。

server.port=8081
#数据源1
spring.datasource.one.password=123
spring.datasource.one.username=root
spring.datasource.one.url=jdbc:mysql:///muljpa1?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
spring.datasource.one.type=com.alibaba.druid.pool.DruidDataSource
#数据源2
spring.datasource.two.password=123
spring.datasource.two.username=root
spring.datasource.two.url=jdbc:mysql:///muljpa2?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
spring.datasource.two.type=com.alibaba.druid.pool.DruidDataSource
#jpa相关配置
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL57InnoDBDialect
spring.jpa.properties.database=mysql
spring.jpa.properties.hibernate.hbm2ddl.auto=update
spring.jpa.properties.show-sql= true

4.配置数据源

创建DataSourceConfig配置数据源,根据application.properties中的配置生成两个数据源

@Configuration
public class DataSourceConfig {@Bean@ConfigurationProperties("spring.datasource.one")@PrimaryDataSource dsOne() {return DruidDataSourceBuilder.create().build();}@Bean@ConfigurationProperties("spring.datasource.two")DataSource dsTwo() {return DruidDataSourceBuilder.create().build();}
}

@DataSourceConfig 中提供两个数据源:dsOne 和dsTwo,默认方法名即为实例名。

@ConfigurationProperties 注解表示使用不同前缀的配置文件来创建不同的DataSource实例。

5.实体类和两个dao(分成两个包,一个是dao1,一个是dao2)

在这里插入图片描述

@Entity(name = "t_user")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {@Id@GeneratedValue(strategy = GenerationType.AUTO)private Integer id;private String name;private String gender;private Integer age;
}
public interface UserDao extends JpaRepository<User,Integer> {
}
public interface UserDao2 extends JpaRepository<User,Integer> {
}

6.创建JPA配置

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = "com.hz.muljpa.dao1",entityManagerFactoryRef = "entityManagerFactoryBeanOne",transactionManagerRef = "platformTransactionManagerOne")
public class JpaConfigOne {@Resource(name = "dsOne")DataSource dsOne;@AutowiredJpaProperties jpaProperties;@Bean@PrimaryLocalContainerEntityManagerFactoryBean entityManagerFactoryBeanOne(EntityManagerFactoryBuilder builder) {return builder.dataSource(dsOne).properties(jpaProperties.getProperties()).packages("com.hz.muljpa.entity").persistenceUnit("pu1").build();}@BeanPlatformTransactionManager platformTransactionManagerOne(EntityManagerFactoryBuilder builder) {LocalContainerEntityManagerFactoryBean factoryOne = entityManagerFactoryBeanOne(builder);return new JpaTransactionManager(factoryOne.getObject());}
}

1.使用@EnableTransactionManagement注解来进行JPA的配置,该注解主要配置三个属性,basePackages用来指定repository所在的位置,entityManagerFactoryRef用来指定用来指定实体类管理工厂Bean的名字(就是上述代码,第一个方法的名字),transactionManagerRef用来指定事务管理器的引用名称,(就是上述代码方法的第二个名字)。

2.LocalContainerEntityManagerFactoryBean 创建该实例来提供entityManager实例,在创建该类过程中,首先设置配置源(dsOne),然后设置jpA的相关配置,在设置实体类所在的位置,最后配置实体化单元,若项目中只有一个EntityManagerFactory,则persistenceUnit可以省略,若有多个,则必须明确指定,对于我们配置多数据来说,肯定是多个,一会我们还要在创建一个jpaconfigTwo类。

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = "com.hz.muljpa.dao2",
entityManagerFactoryRef = "entityManagerFactoryBeanTwo",
transactionManagerRef = "platformTransactionManagerTwo")
public class JpaConfigTwo {@Resource(name = "dsTwo")DataSource dsTwo;@AutowiredJpaProperties jpaProperties;@BeanLocalContainerEntityManagerFactoryBean entityManagerFactoryBeanTwo(EntityManagerFactoryBuilder builder) {return builder.dataSource(dsTwo).properties(jpaProperties.getProperties()).packages("com.hz.muljpa.entity").persistenceUnit("pu2").build();}@BeanPlatformTransactionManager platformTransactionManagerTwo(EntityManagerFactoryBuilder builder) {LocalContainerEntityManagerFactoryBean factoryTwo = entityManagerFactoryBeanTwo(builder);return new JpaTransactionManager(factoryTwo.getObject());}
}

注意这两个类中都有LocalContainerEntityManagerFactoryBean被创建,但只有一个上面加了 @Primary注解,代表该实例优先使用。

7.创建controller

@RestController
public class UserController {@AutowiredUserDao userDao;@AutowiredUserDao2 userDao2;@GetMapping("/testmuijpa")public void test1() {User u1 = new User();u1.setAge(55);u1.setName("鲁迅");u1.setGender("男");userDao.save(u1);User u2 = new User();u2.setAge(80);u2.setName("泰戈尔");u2.setGender("男");userDao2.save(u2);}
}

8.测试

localhost:8081/testmuijpa

查看数据库中有没有数据。

("/testmuijpa")
public void test1() {
User u1 = new User();
u1.setAge(55);
u1.setName(“鲁迅”);
u1.setGender(“男”);
userDao.save(u1);
User u2 = new User();
u2.setAge(80);
u2.setName(“泰戈尔”);
u2.setGender(“男”);
userDao2.save(u2);
}
}


### 8.测试localhost:8081/testmuijpa查看数据库中有没有数据。

这篇关于springboot整合springdata jpa 与多数据源的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/389175

相关文章

Spring Boot @RestControllerAdvice全局异常处理最佳实践

《SpringBoot@RestControllerAdvice全局异常处理最佳实践》本文详解SpringBoot中通过@RestControllerAdvice实现全局异常处理,强调代码复用、统... 目录前言一、为什么要使用全局异常处理?二、核心注解解析1. @RestControllerAdvice2

Spring IoC 容器的使用详解(最新整理)

《SpringIoC容器的使用详解(最新整理)》文章介绍了Spring框架中的应用分层思想与IoC容器原理,通过分层解耦业务逻辑、数据访问等模块,IoC容器利用@Component注解管理Bean... 目录1. 应用分层2. IoC 的介绍3. IoC 容器的使用3.1. bean 的存储3.2. 方法注

Spring事务传播机制最佳实践

《Spring事务传播机制最佳实践》Spring的事务传播机制为我们提供了优雅的解决方案,本文将带您深入理解这一机制,掌握不同场景下的最佳实践,感兴趣的朋友一起看看吧... 目录1. 什么是事务传播行为2. Spring支持的七种事务传播行为2.1 REQUIRED(默认)2.2 SUPPORTS2

怎样通过分析GC日志来定位Java进程的内存问题

《怎样通过分析GC日志来定位Java进程的内存问题》:本文主要介绍怎样通过分析GC日志来定位Java进程的内存问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、GC 日志基础配置1. 启用详细 GC 日志2. 不同收集器的日志格式二、关键指标与分析维度1.

Java进程异常故障定位及排查过程

《Java进程异常故障定位及排查过程》:本文主要介绍Java进程异常故障定位及排查过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、故障发现与初步判断1. 监控系统告警2. 日志初步分析二、核心排查工具与步骤1. 进程状态检查2. CPU 飙升问题3. 内存

java中新生代和老生代的关系说明

《java中新生代和老生代的关系说明》:本文主要介绍java中新生代和老生代的关系说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、内存区域划分新生代老年代二、对象生命周期与晋升流程三、新生代与老年代的协作机制1. 跨代引用处理2. 动态年龄判定3. 空间分

Java设计模式---迭代器模式(Iterator)解读

《Java设计模式---迭代器模式(Iterator)解读》:本文主要介绍Java设计模式---迭代器模式(Iterator),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录1、迭代器(Iterator)1.1、结构1.2、常用方法1.3、本质1、解耦集合与遍历逻辑2、统一

Java内存分配与JVM参数详解(推荐)

《Java内存分配与JVM参数详解(推荐)》本文详解JVM内存结构与参数调整,涵盖堆分代、元空间、GC选择及优化策略,帮助开发者提升性能、避免内存泄漏,本文给大家介绍Java内存分配与JVM参数详解,... 目录引言JVM内存结构JVM参数概述堆内存分配年轻代与老年代调整堆内存大小调整年轻代与老年代比例元空

深度解析Java DTO(最新推荐)

《深度解析JavaDTO(最新推荐)》DTO(DataTransferObject)是一种用于在不同层(如Controller层、Service层)之间传输数据的对象设计模式,其核心目的是封装数据,... 目录一、什么是DTO?DTO的核心特点:二、为什么需要DTO?(对比Entity)三、实际应用场景解析

Java 线程安全与 volatile与单例模式问题及解决方案

《Java线程安全与volatile与单例模式问题及解决方案》文章主要讲解线程安全问题的五个成因(调度随机、变量修改、非原子操作、内存可见性、指令重排序)及解决方案,强调使用volatile关键字... 目录什么是线程安全线程安全问题的产生与解决方案线程的调度是随机的多个线程对同一个变量进行修改线程的修改操