SpringBoot整合JPA详细代码实例

简介:大家好,我是程序员枫哥,🌟一线互联网的IT民工、📝资深面试官、🌹Java跳槽网创始人。拥有多年一线研发经验,曾就职过科大讯飞、美团网、平安等公司。在上海有自己小伙伴组建的副业团队,目前业余时间专注Java技术分享,春招/秋招/社招/跳槽,一对一学习辅助,项目接活开发。
🌈更多学习内容, 欢迎👏关注👀【文末】微信公众号:IT枫斗者
🌟🌟程序员找工作,就上Java跳槽网:www.javatiaocao.com

SpringBoot整合JPA详细代码实例

Spring Data JPA概述

  • SpringData:Spring 的一个子项目。用于简化数据库访问,支持NoSQL 和 关系数据存储。其主要目标是使数据库的访问变得方便快捷。
  • JPA:JPA(Java Persistence API,Java持久化API),定义了对象关系映射(Object Relation Mapping,ORM)以及实体对象持久化的标准接口。Hibernate实现了JPA的一个ORM框架。
  • JPA Spring Data:致力于减少数据访问层 (DAO) 的开发量,开发者唯一要做的,就只是声明持久层的接口,其他都交给 Spring Data JPA 来完成。Spring Data JPA 是Spring基于ORM框架、JPA规范的基础上封装的一套JPA应用框架。

SpringBoot整合JPA

建库建表

  • DROP TABLE IF EXISTS  student ;
    CREATE TABLE  student  (
       id  int(11) NOT NULL AUTO_INCREMENT,
       name  varchar(100) DEFAULT NULL,
       sex  varchar(100) DEFAULT NULL,
       age  int(11) DEFAULT NULL,
      PRIMARY KEY ( id )
    ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
    
  • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

新建项目

  • 目录结构如下:
  • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

添加相关依赖

  • <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    	<modelVersion>4.0.0</modelVersion>
    	<parent>
    		<groupId>org.springframework.boot</groupId>
    		<artifactId>spring-boot-starter-parent</artifactId>
    		<version>2.5.4</version>
    		<relativePath/>
    	</parent>
    	<groupId>com.jpa.mysql</groupId>
    	<artifactId>spring-data-jpa-mysql</artifactId>
    	<version>0.0.1-SNAPSHOT</version>
    	<name>spring-data-jpa-mysql</name>
    	<description>spring-data-jpa-mysql</description>
    
    	<properties>
    		<java.version>1.8</java.version>
    	</properties>
    
    	<dependencies>
    
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-web</artifactId>
    		</dependency>
    
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter</artifactId>
    		</dependency>
    
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-test</artifactId>
    			<scope>test</scope>
    		</dependency>
    
    		<!-- jpa 依赖-->
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-data-jpa</artifactId>
    		</dependency>
    
    		<!-- lombok 依赖-->
    		<dependency>
    			<groupId>org.projectlombok</groupId>
    			<artifactId>lombok</artifactId>
    			<optional>true</optional>
    		</dependency>
    
    		<dependency>
    			<groupId>mysql</groupId>
    			<artifactId>mysql-connector-java</artifactId>
    		</dependency>
    
    	</dependencies>
    
    	<build>
    		<plugins>
    			<plugin>
    				<groupId>org.springframework.boot</groupId>
    				<artifactId>spring-boot-maven-plugin</artifactId>
    			</plugin>
    		</plugins>
    	</build>
    
    </project>
    

修改application.properties配置文件

  • server.port=9000
    spring.datasource.driver-class-name=com.mysql.jdbc.Driver
    spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test
    spring.datasource.username=root
    spring.datasource.password=root
    spring.jpa.show-sql=true
    spring.jpa.database-platform=org.hibernate.dialect.MySQL5Dialect
    

编写entity

  • package com.jpa.mysql.entity;
    
    import lombok.Data;
    
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.Id;
    import javax.persistence.Table;
    import java.io.Serializable;
    
    @Data
    @Entity
    @Table(name = "student")
    public class Student implements Serializable {
    
        @Id
        @Column(name="id")
        private int id;
    
        @Column(name="name")
        private String name;
    
        @Column(name="sex")
        private String sex;
    
        @Column(name="age")
        private int age;
    }
    

编写dao

  • package com.jpa.gbase.dao;
    
    import com.jpa.gbase.entity.Student;
    import org.springframework.data.jpa.repository.JpaRepository;
    import org.springframework.stereotype.Repository;
    
    import java.util.List;
    
    @Repository
    public interface StudentDao extends JpaRepository<Student, Integer> {
    
        List<Student> findByName(String name);
    }
    

编写service接口

  • package com.jpa.gbase.service;
    import com.jpa.gbase.entity.Student;
    import org.springframework.stereotype.Component;
    import java.util.List;
    @Component
    public interface IStudentService {
        Student findById(Integer id);
        List<Student> findAll();
        List<Student> findByName(String name);
        Student save(String name) throws Exception;
        void delete(Integer id) throws Exception;
    }
    

编写service实现类

  • package com.jpa.gbase.service.impl;
    
    import com.jpa.gbase.dao.StudentDao;
    import com.jpa.gbase.entity.Student;
    import com.jpa.gbase.service.IStudentService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    import org.springframework.transaction.annotation.Transactional;
    
    import java.util.List;
    
    @Component
    public class StudentServiceImpl implements IStudentService {
    
        @Autowired
        private StudentDao studentDao;
    
        @Override
        public Student findById(Integer id) {
            return studentDao.findById(id).get();
        }
    
        @Override
        public List<Student> findAll() {
            return studentDao.findAll();
        }
    
        @Override
        public List<Student> findByName(String name) {
            return studentDao.findByName(name);
        }
    
        @Override
        @Transactional
        public Student save(String name) throws Exception {
            Student student = new Student();
            student.setName(name);
            student.setSex("M");
            student.setAge(18);
            return studentDao.save(student);
        }
    
        @Override
        @Transactional
        public void delete(Integer id) throws Exception {
            studentDao.deleteById(id);
        }
    }
    

编写controller

  • package com.jpa.gbase.controller;
    
    import com.jpa.gbase.entity.Student;
    import com.jpa.gbase.service.IStudentService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RestController;
    
    import java.util.List;
    
    @RestController
    @RequestMapping(value = "/student")
    public class StudentController {
    
        @Autowired
        private IStudentService studentService;
    
        @GetMapping(value = "/findById/{id}")
        public Student findById(@PathVariable("id") Integer id) {
            return studentService.findById(id);
        }
    
        @GetMapping(value = "/findAll")
        public List<Student> findAll() {
            return studentService.findAll();
        }
    
        @GetMapping(value = "/findByName/{name}")
        public List<Student> findByName(@PathVariable("name") String name) {
            return studentService.findByName(name);
        }
    
        @GetMapping(value = "/save/{name}")
        public Student save(@PathVariable("name") String name) {
            Student student = new Student();
            try {
                student = studentService.save(name);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return student;
    
        }
    
        @GetMapping(value = "/delete/{id}")
        public boolean delete(@PathVariable("id") Integer id) {
            boolean flg = false;
            try {
                studentService.delete(id);
                flg = true;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return flg;
        }
    }
    

编写启动类

  • package com.jpa.mysql;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    @SpringBootApplication
    public class SpringDataJpaMysqlApplication {
    
    	public static void main(String[] args) {
    SpringApplication.run(SpringDataJpaMysqlApplication.class, args);
    	}
    
    
    

简单查询

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

预先生成方法

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

  • 继承 JpaRepository

  • @Repository
    public interface StudentDao extends JpaRepository<Student, Integer> {
    }
    
  • 使用默认方法

  • @Autowired
    private StudentDao studentDao;
    
    studentDao.findAll();
    studentDao.findOne(1l);
    studentDao.save(user);
    studentDao.delete(user);
    studentDao.count();
    studentDao.exists(1l);
    

自定义简单查询

  • 自定义的简单查询就是根据方法名来自动生成 SQL。

  • 主要的语法是 findByXX,readAByXX,queryByXX,countByXX, getByXX XX 代表属性名称。

  • Student findByName(String name);
    
  • 也使用一些加一些关键字And Or

  • User findByNameOrSex(String username, int sex);
    
  • 修改、删除、统计也是类似语法:

  • Long deleteById(Long id);
    Long countByName(String mame);
    
  • 基本上 SQL 体系中的关键词都可以使用,例如:LIKEIgnoreCaseOrderBy

  • List<Student> findByNameLike(String name);
    Student findByNameIgnoreCase(String name);
    List<Student> findByNameOrderByAgeDesc(String name);
    
  • 具体的关键字,使用方法和生产成SQL如下表所示:

  • KeywordSampleJPQL snippet
    AndfindByLastnameAndFirstname… where x.lastname = ?1 and x.firstname = ?2
    OrfindByLastnameOrFirstname… where x.lastname = ?1 or x.firstname = ?2
    Is,EqualsfindByFirstnameIs,findByFirstnameEquals… where x.firstname = ?1
    BetweenfindByStartDateBetween… where x.startDate between ?1 and ?2
    LessThanfindByAgeLessThan… where x.age < ?1
    LessThanEqualfindByAgeLessThanEqual… where x.age <= ?1
    GreaterThanfindByAgeGreaterThan… where x.age > ?1
    GreaterThanEqualfindByAgeGreaterThanEqual… where x.age >= ?1
    AfterfindByStartDateAfter… where x.startDate > ?1
    BeforefindByStartDateBefore… where x.startDate < ?1
    IsNullfindByAgeIsNull… where x.age is null
    IsNotNull,NotNullfindByAge(Is)NotNull… where x.age not null
    LikefindByFirstnameLike… where x.firstname like ?1
    NotLikefindByFirstnameNotLike… where x.firstname not like ?1
    StartingWithfindByFirstnameStartingWith… where x.firstname like ?1 (parameter bound with appended %)
    EndingWithfindByFirstnameEndingWith… where x.firstname like ?1 (parameter bound with prepended %)
    ContainingfindByFirstnameContaining… where x.firstname like ?1 (parameter bound wrapped in %)
    OrderByfindByAgeOrderByLastnameDesc… where x.age = ?1 order by x.lastname desc
    NotfindByLastnameNot… where x.lastname <> ?1
    InfindByAgeIn(Collection ages)… where x.age in ?1
    NotInfindByAgeNotIn(Collection age)… where x.age not in ?1
    TRUEfindByActiveTrue()… where x.active = true
    FALSEfindByActiveFalse()… where x.active = false
    IgnoreCasefindByFirstnameIgnoreCase… where UPPER(x.firstame) = UPPER(?1)

复杂查询

  • 在实际的开发中我们需要用到分页、删选、连表等查询的时候就需要特殊的方法或者自定义 SQL。

分页查询

  • 分页查询在实际使用中非常普遍了,Spring Boot Jpa 已经帮我们实现了分页的功能,在查询的方法中,需要传入

  • 参数Pageable ,当查询中有多个参数的时候Pageable建议做为最后一个参数传入。

  • Page<Student> findALL(Pageable pageable);
    Page<Student> findByName(String name,Pageable pageable);
    
  • Pageable 是 Spring 封装的分页实现类,使用的时候需要传入页数、每页条数和排序规则。

  • @Test
    public void testPageQuery() throws Exception {
    	int page=1,size=10;
    	Sort sort = new Sort(Direction.DESC, "id");
        Pageable pageable = new PageRequest(page, size, sort);
        studentDao.findALL(pageable);
        studentDao.findByName("tom", pageable);
    }
    

限制查询

  • 有时候我们只需要查询前N个元素,或者只取前一个实体。

  • Student findFirstByOrderByNameAsc();
    Student findTopByOrderByAgeDesc();
    Page&lt;Student&gt; queryFirst10ByName(String name, Pageable pageable);
    List&lt;Student&gt; findFirst10ByName(String name, Sort sort);
    List&lt;Student&gt; findTop10ByName(String name, Pageable pageable);
    

自定义SQL查询

  • 其实 Spring Data 觉大部分的 SQL 都可以根据方法名定义的方式来实现,但是由于某些原因我们想使用自定义的SQL 来查询,Spring Data 也是完美支持的;在 SQL 的查询方法上面使用@Query注解,如涉及到删除和修改再需要加上@Modifying,也可以根据需要添加 @Transactional对事物的支持,查询超时的设置等。

  • @Modifying
    @Query("update student stu set stu.name = ?1 where stu.id = ?2")
    int modifyNameById(String name, Long id);
    	
    @Transactional
    @Modifying
    @Query("delete from student where id = ?1")
    void deleteById(Long id);
    
    @Transactional(timeout = 10)
    @Query("select stu from student stu where stu.id = ?1")
    User findById(Long id);
    

多表查询

  • 多表查询 Spring Boot Jpa 中有两种实现方式,第一种是利用 Hibernate 的级联查询来实现,第二种是创建一个结果集的接口来接收连表查询后的结果,这里主要第二种方式。首先需要定义一个结果集的接口类:

  • public interface HotelSummary {
    	City getCity();
    	String getName();
    	Double getAverageRating();
    	default Integer getAverageRatingRounded() {
    		return getAverageRating() == null ? null : (int) Math.round(getAverageRating());
    	}
    }
    
  • 查询的方法返回类型设置为新创建的接口:

  • @Query("select h.city as city, h.name as name, avg(r.rating) as averageRating "
    		- "from Hotel h left outer join h.reviews r where h.city = ?1 group by h")
    Page<HotelSummary> findByCity(City city, Pageable pageable);
    
    @Query("select h.name as name, avg(r.rating) as averageRating "
    		- "from Hotel h left outer join h.reviews r  group by h")
    Page<HotelSummary> findByCity(Pageable pageable);
    
  • 使用:

  • Page<HotelSummary> hotels = this.hotelRepository.findByCity(new PageRequest(0, 10, Direction.ASC, "name"));
    for(HotelSummary summay:hotels){
    		System.out.println("Name" +summay.getName());
    	}
    
  • 在运行中 Spring 会给接口(HotelSummary)自动生产一个代理类来接收返回的结果,代码汇总使用 getXX的形式来获取。

使用枚举

  • 使用枚举的时候,我们希望数据库中存储的是枚举对应的 String 类型,而不是枚举的索引值,需要在属性上面添加@Enumerated(EnumType.STRING) 注解

  • @Enumerated(EnumType.STRING) 
    @Column(nullable = true)
    private UserType type;
    

不需要和数据库映射的属性

  • 正常情况下我们在实体类上加入注解@Entity,就会让实体类和表相关连如果其中某个属性我们不需要和数据库来关联只是在展示的时候做计算,只需要加上@Transient属性既可。

  • @Transient
    private String userName;
    

多数据源的支持

同源数据库的多源支持

  • 日常项目中因为使用的分布式开发模式,不同的服务有不同的数据源,常常需要在一个项目中使用多个数据源,因此需要配置 Spring Boot Jpa 对多数据源的使用,一般分一下为三步:
    • 1 配置多数据源
    • 2 不同源的实体类放入不同包路径
    • 3 声明不同的包路径下使用不同的数据源、事务支持

异构数据库多源支持

  • 比如我们的项目中,即需要对 mysql 的支持,也需要对 Mongodb 的查询等。实体类声明@Entity 关系型数据库支持类型,声明@Document 为 Mongodb 支持类型,不同的数据源使用不同的实体就可以了。

  • interface PersonRepository extends Repository<Person, Long> {
     …
    }
    
    @Entity
    public class Person {
      …
    }
    
    interface UserRepository extends Repository<User, Long> {
     …
    }
    
    @Document
    public class User {
      …
    }
    
  • 但是,如果 User 用户既使用 Mysql 也使用 Mongodb 呢,也可以做混合使用。

  • interface JpaPersonRepository extends Repository<Person, Long> {
     …
    }
    
    interface MongoDBPersonRepository extends Repository<Person, Long> {
     …
    }
    
    @Entity
    @Document
    public class Person {
      …
    }
    
  • 也可以通过对不同的包路径进行声明,比如 A 包路径下使用 mysql,B 包路径下使用 MongoDB。

  • @EnableJpaRepositories(basePackages = "com.neo.repositories.jpa")
    @EnableMongoRepositories(basePackages = "com.neo.repositories.mongo")
    interface Configuration { }
    

多数据源使用案例

导入pom依赖

  • <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.5.4</version>
            <relativePath/>
        </parent>
    
        <groupId>com.example</groupId>
        <artifactId>spring-boot-multi-jpa</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>spring-boot-multi-jpa</name>
        <description>spring-boot-multi-Jpa</description>
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <java.version>1.8</java.version>
        </properties>
    
        <dependencies>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-jpa</artifactId>
            </dependency>
    
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
            </dependency>
    
            <!-- lombok 依赖-->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <optional>true</optional>
            </dependency>
    
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <scope>test</scope>
            </dependency>
    
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>
    

配置文件

  • spring.datasource.primary.jdbc-url=jdbc:mysql://localhost:3306/test1?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true
    spring.datasource.primary.username=root
    spring.datasource.primary.password=root
    spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver
    
    spring.datasource.secondary.jdbc-url=jdbc:mysql://localhost:3306/test2?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true
    spring.datasource.secondary.username=root
    spring.datasource.secondary.password=root
    spring.datasource.secondary.driver-class-name=com.mysql.cj.jdbc.Driver
    
    spring.jpa.show-sql=true
    spring.jpa.properties.hibernate.hbm2ddl.auto=create
    spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
    spring.jpa.properties.hibernate.format_sql=true
    

实体类

  • package com.example.springbootmultijpa.model;
    
    import lombok.AllArgsConstructor;
    import lombok.Getter;
    import lombok.NoArgsConstructor;
    import lombok.Setter;
    
    import javax.persistence.*;
    import java.io.Serializable;
    
    @Getter
    @Setter
    @Entity
    @NoArgsConstructor
    @AllArgsConstructor
    public class User implements Serializable {
    
        private static final long serialVersionUID = 1L;
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Column(name = "id")
        private long id;
    
        @Column(nullable = false, unique = true)
        private String userName;
    
        @Column(nullable = false)
        private String passWord;
    
        @Column(nullable = false, unique = true)
        private String email;
    
        @Column(nullable = true, unique = true)
        private String nickName;
    
        @Column(nullable = false)
        private String regTime;
    
        public User(String userName, String passWord, String email, String nickName, String regTime) {
            this.userName = userName;
            this.passWord = passWord;
            this.email = email;
            this.nickName = nickName;
            this.regTime = regTime;
        }
    }
    

config

  • package com.example.springbootmultijpa.config;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties;
    import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings;
    import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.boot.jdbc.DataSourceBuilder;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Primary;
    
    import javax.sql.DataSource;
    import java.util.Map;
    
    @Configuration
    public class DataSourceConfig {
    
        @Autowired
        private JpaProperties jpaProperties;
    
        @Autowired
        private HibernateProperties hibernateProperties;
    
        @Bean(name = "primaryDataSource")
        @Primary
        @ConfigurationProperties("spring.datasource.primary")
        public DataSource firstDataSource() {
            return DataSourceBuilder.create().build();
        }
    
        @Bean(name = "secondaryDataSource")
        @ConfigurationProperties("spring.datasource.secondary")
        public DataSource secondDataSource() {
            return DataSourceBuilder.create().build();
        }
    
        @Bean(name = "vendorProperties")
        public Map<String, Object> getVendorProperties() {
            return hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(),
                    new HibernateSettings());
        }
    }
    
  • package com.example.springbootmultijpa.config;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Primary;
    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;
    
    import javax.persistence.EntityManager;
    import javax.sql.DataSource;
    import java.util.Map;
    
    @Configuration
    @EnableTransactionManagement
    @EnableJpaRepositories(
            entityManagerFactoryRef = "entityManagerFactoryPrimary",
            transactionManagerRef = "transactionManagerPrimary",
            basePackages = {"com.example.springbootmultijpa.repository.test1"})//设置dao(repo)所在位置
    public class PrimaryConfig {
    
        @Autowired
        @Qualifier("primaryDataSource")
        private DataSource primaryDataSource;
    
        @Autowired
        @Qualifier("vendorProperties")
        private Map<String, Object> vendorProperties;
    
        @Bean(name = "entityManagerFactoryPrimary")
        @Primary
        public LocalContainerEntityManagerFactoryBean entityManagerFactoryPrimary(EntityManagerFactoryBuilder builder) {
            return builder
                    .dataSource(primaryDataSource)
                    .properties(vendorProperties)
                    .packages("com.example.springbootmultijpa.model") //设置实体类所在位置
                    .persistenceUnit("primaryPersistenceUnit")
                    .build();
        }
    
        @Bean(name = "entityManagerPrimary")
        @Primary
        public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
            return entityManagerFactoryPrimary(builder).getObject().createEntityManager();
        }
    
        @Bean(name = "transactionManagerPrimary")
        @Primary
        PlatformTransactionManager transactionManagerPrimary(EntityManagerFactoryBuilder builder) {
            return new JpaTransactionManager(entityManagerFactoryPrimary(builder).getObject());
        }
    }
    
  • package com.example.springbootmultijpa.config;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    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;
    
    import javax.persistence.EntityManager;
    import javax.sql.DataSource;
    import java.util.Map;
    
    @Configuration
    @EnableTransactionManagement
    @EnableJpaRepositories(
            entityManagerFactoryRef = "entityManagerFactorySecondary",
            transactionManagerRef = "transactionManagerSecondary",
            basePackages = {"com.example.springbootmultijpa.repository.test2"})
    public class SecondaryConfig {
    
        @Autowired
        @Qualifier("secondaryDataSource")
        private DataSource secondaryDataSource;
    
        @Autowired
        @Qualifier("vendorProperties")
        private Map<String, Object> vendorProperties;
    
        @Bean(name = "entityManagerFactorySecondary")
        public LocalContainerEntityManagerFactoryBean entityManagerFactorySecondary(EntityManagerFactoryBuilder builder) {
            return builder
                    .dataSource(secondaryDataSource)
                    .properties(vendorProperties)
                    .packages("com.example.springbootmultijpa.model")
                    .persistenceUnit("secondaryPersistenceUnit")
                    .build();
        }
    
        @Bean(name = "entityManagerSecondary")
        public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
            return entityManagerFactorySecondary(builder).getObject().createEntityManager();
        }
    
        @Bean(name = "transactionManagerSecondary")
        PlatformTransactionManager transactionManagerSecondary(EntityManagerFactoryBuilder builder) {
            return new JpaTransactionManager(entityManagerFactorySecondary(builder).getObject());
        }
    }
    

Repository

  • package com.example.springbootmultijpa.repository.test1;
    
    import com.example.springbootmultijpa.model.User;
    import org.springframework.data.jpa.repository.JpaRepository;
    
    public interface UserTest1Repository extends JpaRepository<User, Long> {
        User findById(long id);
    
        User findByUserName(String userName);
    
        User findByUserNameOrEmail(String username, String email);
    }
    

启动类

  • package com.example.springbootmultijpa;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    @SpringBootApplication
    public class SpringBootMultiJpaApplication {
        public static void main(String[] args) {   SpringApplication.run(SpringBootMultiJpaApplication.class, args);
        }
    }
    

测试

  • package com.example.springbootmultijpa.repository;
    
    import com.example.springbootmultijpa.model.User;
    import com.example.springbootmultijpa.repository.test1.UserTest1Repository;
    import com.example.springbootmultijpa.repository.test2.UserTest2Repository;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit4.SpringRunner;
    
    import javax.annotation.Resource;
    import java.text.DateFormat;
    import java.util.Date;
    
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class UserRepositoryTests {
    
        @Resource
        private UserTest1Repository userTest1Repository;
        @Resource
        private UserTest2Repository userTest2Repository;
    
        @Test
        public void testSave() throws Exception {
            Date date = new Date();
            DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG);
            String formattedDate = dateFormat.format(date);
            userTest1Repository.save(new User("aa", "aa123456", "aa@126.com", "aa", formattedDate));
            userTest1Repository.save(new User("bb", "bb123456", "bb@126.com", "bb", formattedDate));
            userTest2Repository.save(new User("cc", "cc123456", "cc@126.com", "cc", formattedDate));
        }
    
        @Test
        public void testDelete() throws Exception {
            userTest1Repository.deleteAll();
            userTest2Repository.deleteAll();
        }
    
        @Test
        public void testBaseQuery() {
            Date date = new Date();
            DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG);
            String formattedDate = dateFormat.format(date);
            User user = new User("ff", "ff123456", "ff@126.com", "ff", formattedDate);
            userTest1Repository.findAll();
            userTest2Repository.findById(3l);
            userTest2Repository.save(user);
            user.setId(2l);
            userTest1Repository.delete(user);
            userTest1Repository.count();
            userTest2Repository.findById(3l);
        }
    }
    
  • 运行testSave()得到的结

  • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 运行testBaseQuery()得到的结果:

  • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT枫斗者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值