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

相关文章

springboot集成easypoi导出word换行处理过程

《springboot集成easypoi导出word换行处理过程》SpringBoot集成Easypoi导出Word时,换行符n失效显示为空格,解决方法包括生成段落或替换模板中n为回车,同时需确... 目录项目场景问题描述解决方案第一种:生成段落的方式第二种:替换模板的情况,换行符替换成回车总结项目场景s

SpringBoot集成redisson实现延时队列教程

《SpringBoot集成redisson实现延时队列教程》文章介绍了使用Redisson实现延迟队列的完整步骤,包括依赖导入、Redis配置、工具类封装、业务枚举定义、执行器实现、Bean创建、消费... 目录1、先给项目导入Redisson依赖2、配置redis3、创建 RedissonConfig 配

SpringBoot中@Value注入静态变量方式

《SpringBoot中@Value注入静态变量方式》SpringBoot中静态变量无法直接用@Value注入,需通过setter方法,@Value(${})从属性文件获取值,@Value(#{})用... 目录项目场景解决方案注解说明1、@Value("${}")使用示例2、@Value("#{}"php

SpringBoot分段处理List集合多线程批量插入数据方式

《SpringBoot分段处理List集合多线程批量插入数据方式》文章介绍如何处理大数据量List批量插入数据库的优化方案:通过拆分List并分配独立线程处理,结合Spring线程池与异步方法提升效率... 目录项目场景解决方案1.实体类2.Mapper3.spring容器注入线程池bejsan对象4.创建

线上Java OOM问题定位与解决方案超详细解析

《线上JavaOOM问题定位与解决方案超详细解析》OOM是JVM抛出的错误,表示内存分配失败,:本文主要介绍线上JavaOOM问题定位与解决方案的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录一、OOM问题核心认知1.1 OOM定义与技术定位1.2 OOM常见类型及技术特征二、OOM问题定位工具

基于 Cursor 开发 Spring Boot 项目详细攻略

《基于Cursor开发SpringBoot项目详细攻略》Cursor是集成GPT4、Claude3.5等LLM的VSCode类AI编程工具,支持SpringBoot项目开发全流程,涵盖环境配... 目录cursor是什么?基于 Cursor 开发 Spring Boot 项目完整指南1. 环境准备2. 创建

Spring Security简介、使用与最佳实践

《SpringSecurity简介、使用与最佳实践》SpringSecurity是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架,本文给大家介绍SpringSec... 目录一、如何理解 Spring Security?—— 核心思想二、如何在 Java 项目中使用?——

SpringBoot+RustFS 实现文件切片极速上传的实例代码

《SpringBoot+RustFS实现文件切片极速上传的实例代码》本文介绍利用SpringBoot和RustFS构建高性能文件切片上传系统,实现大文件秒传、断点续传和分片上传等功能,具有一定的参考... 目录一、为什么选择 RustFS + SpringBoot?二、环境准备与部署2.1 安装 RustF

springboot中使用okhttp3的小结

《springboot中使用okhttp3的小结》OkHttp3是一个JavaHTTP客户端,可以处理各种请求类型,比如GET、POST、PUT等,并且支持高效的HTTP连接池、请求和响应缓存、以及异... 在 Spring Boot 项目中使用 OkHttp3 进行 HTTP 请求是一个高效且流行的方式。

java.sql.SQLTransientConnectionException连接超时异常原因及解决方案

《java.sql.SQLTransientConnectionException连接超时异常原因及解决方案》:本文主要介绍java.sql.SQLTransientConnectionExcep... 目录一、引言二、异常信息分析三、可能的原因3.1 连接池配置不合理3.2 数据库负载过高3.3 连接泄漏