springboot(MyBatis多数据源配置与JPA)

编程入门 行业动态 更新时间:2024-10-10 05:27:05

<a href=https://www.elefans.com/category/jswz/34/1769943.html style=springboot(MyBatis多数据源配置与JPA)"/>

springboot(MyBatis多数据源配置与JPA)

文章目录

    • 基于Mybatis配置多数据源
    • SpringBoot中如何集成spring data jpa
      • 一 什么是ORM
      • 二 什么是JPA
      • 三 什么是Spring Data Jpa?
      • 四 Spring Data JPA 和 Mybatis对比
      • 五 Springboot 中如何集成spring data jpa
      • 六 Spring Data Api 核心接口
      • 七 JpaRepository接口的基本应用
      • 八 spring data jpa 自定义查询
      • 九 自定义sql
      • 十 复杂查询
      • 十一 **JpaSpecificationExcutor** 的使用
      • 十二 JPQL
      • 十三 基于jpa 配置多数据源

基于Mybatis配置多数据源

导入mysql驱动,mybatis,lombok

  1. 在 application.properties 中配置数据源信息

    #数据源1
    spring.datasource.one.driver-class-name=com.mysql.cj.jdbc.Driver
    spring.datasource.one.jdbc-url=jdbc:mysql://localhost:3306/boot1?characterEncoding=utf8&serverTimezone=GMT%2B8
    spring.datasource.one.username=root
    spring.datasource.one.password=034312#需要注意的是,springboot2.0以上配置双数据源,配置文件中不能写url,而是要改成jdbc-url,否则会出错。#数据源2
    spring.datasource.two.driver-class-name=com.mysql.cj.jdbc.Driver
    spring.datasource.two.jdbc-url=jdbc:mysql://localhost:3306/boot2?characterEncoding=utf8&serverTimezone=GMT%2B8
    spring.datasource.two.username=root
    spring.datasource.two.password=034312
    
  2. 创建DataSourceConfig配置类

    @Configuration
    public class DataSourceConfig {@Bean@ConfigurationProperties(prefix = "spring.datasource.one")DataSource dsOne() {return DataSourceBuilder.create().build();}@Bean@ConfigurationProperties(prefix = "spring.datasource.two")DataSource dsTwo() {return DataSourceBuilder.create().build();}
    }
    
  3. 创建MybatisConfig***配置类

    以MybatisConfiOne为例

    @Configuration
    @MapperScan(basePackages = "com.zhj.mapper1",sqlSessionTemplateRef = "sqlSessionTemplate1")
    public class MyBatisConfigOne {@Resource(name = "dsOne")DataSource dsOne;@BeanSqlSessionFactory sqlSessionFactory1() {SqlSessionFactory sessionFactory = null;try {SqlSessionFactoryBean bean = new SqlSessionFactoryBean();bean.setDataSource(dsOne);bean.setTypeAliasesPackage("com.zhj.domain");sessionFactory = bean.getObject();} catch (Exception e) {e.printStackTrace();}return sessionFactory;}@BeanSqlSessionTemplate sqlSessionTemplate1() {return new SqlSessionTemplate(sqlSessionFactory1());}
    }
    
  4. 然后 后面正常创建 对应的 mapper ,service,controller

  5. 注意: pom文件配置

    <resources><resource><directory>src/main/java</directory><includes><include>**/*.xml</include></includes><filtering>true</filtering></resource><resource><directory>src/main/resources</directory></resource>
    </resources> 
    

SpringBoot中如何集成spring data jpa

一 什么是ORM

​ ORM即Object-Relational Mapping,他的作用是关系型数据库和对象之间的映射。这样,我们在具体操作数据库的时候,就不需要和复杂的SQL语句打交道,只要像平常操作对象操作他就可以了

​ 在ORM出现之前,我们使用jdbc来操作数据库,但jdbc没有封装,对于大项目来说,很难实现MVC的概念,所以人们就开发了 ORM框架来解决这些问题。比如Hibernate,Mybatis,不过 Hibernate是完全的ORM框架,mybatis是半ORM框架,因为它需要手动建表和自己写sql

​ ORM的优点:提高了开发效率。由于ORM可以自动对Entity对象与数据库中的table进行字段与属性的映射,能够像操作对象一样 从数据库中获取数据

​ ORM的缺点:ORM的缺点是牺牲程序的执行效率,因为是自动生成的sql,所以实现复杂查询比较麻烦

二 什么是JPA

​ ORM框架很多,大家各自搞自己的,为了统一规范,就出了JPA

​ JPA全称Java Persistence API ,可以通过注解 或者 XML描述【对象-关系表】之间的映射关系,并将对象持久化到数据库中

​ JPA为我们提供了:

​ (1)ORM映射元数据:JPA 支持XML 和 注解两种元数据形式,元数据描述对象与对象之间的映射关系,框架据此将实体对象持久化到数据库表中

​ 如:@Entity,@Table,@Column,@Transient等注解

​ (2)API:用来操作实体对象,执行CRUD操作,框架在后台替我们完成所有的事情,开发者从繁琐的JDBC和SQL代码中解脱出来

​ 如:entityMananger.merge(T t)

​ (3)JPQL查询语言:通过面向对象而非面向数据库的查询语言查询数据,避免程序的SQL语句紧密耦合

​ 但是:JPA仅仅是一种规范,也就是说JPA仅仅定义了一些接口,而接口需要实现才能工作,所以底层需要某种实现

​ 而Hibernate就是实现了JPA接口的ORM框架

三 什么是Spring Data Jpa?

​ 实现jpa中的接口需要写大量的代码,包括简单的增删改查,那可不可以有框架将这些写好呢,于是Spring Data Jpa 就出现了

​ Spring Data Jpa是spring提供一套简化JPA开发的框架,不仅有接口,也有实现类,只要按照约定好的【命名规则】写dao接口,就可以在不写接口实现的情况下,实现对数据库的访问和操作,同时提供了很多处理CRUD之外的功能,如分页 排序 复杂查询;

​ Spring Data JPA可以理解为JPA规范的再次封装抽象,底层还是使用了Hibernate的JPA技术实现

四 Spring Data JPA 和 Mybatis对比

​ 关于在开发中到底应该是使用JPA 还是使用 Mybatis 争论不休,总体来说,国外用JPA的多,国内用MyBatis的多

Spiring Data JPA是面向对象的思想,一个对象就是一个类,强化的是您对这个表的控制。spring data jpa实现了jpa 功能,即 可以实现pojo 转化为关系型数据库记录的功能,通俗来讲 可以不写任何建表sql 语句了。jpa 是spring data jpa功能的一个子集

MyBatis则是面向sql,您的结果完全来源于sql,而对象这个东西只是用来接受sql带来的结果集。您的一切操作都是围绕sql,包括动态根据条件约定sql语句等。mybatis并不是注意对象的概念。只要能接受数据就好

各自优缺点

​ 面向sql就更利于优化,因为sql可以优化的点太多的了。对于并发用户多,主求性能的,mybatis 更有优势。

​ 面向对象就更利于移植,可维护性,因为数据对象不依赖数据源。比如mysql换成oracle,jpa更方便。

​ 用哪个 最终取决于老板

五 Springboot 中如何集成spring data jpa

​ Spring boot 中使用JPA 实际上是Spring Data JPA ,在 Spring Data 中,只要您的方法名符合规范,他就知道您想干什么,不许要自己再去写SQL。

  1. 创建工程

    创建工程,添加Web,Jpa,MySql驱动,lombok依赖

  2. 添加druid 连接池依赖

    springboot默认的连接是hikari

    <!-- .alibaba/druid --><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.6</version></dependency>
    
  3. 配置连接信息 和 jpa 信息(application.properties)

    # 配置数据库基本信息
    spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
    spring.datasource.url=jdbc:mysql://localhost:3306/boot3?useUnicode=true&characterEncoding=utf8
    spring.datasource.username=root
    spring.datasource.password=034312
    # 更换数据源类型
    spring.datasource.type=com.alibaba.druid.pool.DruidDataSource# 配置JPA
    spring.jpa.database=mysql# 是否在控制台打印SQL
    spring.jpa.show-sql=true# 每次启动项目,数据库初始化策略
    #spring.jpa.hibernate.ddl-auto=create # 每次运行该程序没有表格会新建表,表内数据会清空
    #spring.jpa.hibernate.ddl-auto=create-drop # 每次程序结束是会会清空表
    #spring.jpa.hibernate.ddl-auto=update # 每次运行程序,没有表格会新建,表内有数据不会清空,只会更新
    #spring.jpa.hibernate.ddl-auto=validate # 运行程序会校验数据库 与 对象 中字段类型是否相同,不同会报错spring.jpa.hibernate.ddl-auto=update# 指定默认存储引擎为InnoDB,默认情况下自动创建表时会使用 MyISAM 作为表引擎
    spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL57Dialect
    
  4. 创建domain

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @Entity(name = "user")
    public class User {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Integer id;@Column(name = "name")private String name;@Column(name = "pwd")private String pwd;
    }
    
  5. 创建mapper

    public interface UserMapper extends JpaRepository<User,Integer> {
    }
    
  6. 在service 直接进行属性注入即可

六 Spring Data Api 核心接口

  1. Repository接口

    提供方法名称命名查询方式

    提供了基于@Query注解查询与 更新

  2. CrudRepository接口

    CrudRepository接口继承了Repository接口

    CrudRepository提供了基本的增删改查,不需要我们自定义

  3. PagingAndSortingRepository接口

    该接口继承了CrudRepository接口

    该该接口提供了分页与排序操作,也就是该接口不用自己定义增删改查方法和分页排序方法

  4. JpaRepository接口

    该接口继承了PagingAndSortingRepository

    对继承的父接口中的方法的返回值进行适配,也就是该接口不用自己定义增删改查和分页排序方法,并且让分页查询更加简单

  5. JpaSpecificationExcutor接口

    该接口主要是提供了多条件查询的支持,并且可以在查询中添加排序和分页。注意JPASpecificationExcutor是单独存在的。不继承上述接口

七 JpaRepository接口的基本应用

​ @Autowired

​ private Mapper mapper;

查询所有:mapper.findAll()

查询单个:mapper.findById(id),get()

添加: mapper.save(domain)

修改用户: mapper.getOne(id) mapper.save(domain)

删除用户:mapper.delete()

分页查询

public List<User> selectUserByPage(){PageRequest pageRequest = PageRequest.of(0, 3);Page<User> page = userMapper.findAll(pageRequest);List<User> userList = page.getContent();return userList;
}

降序查询

public List<User> selectUserBySort(){PageRequest pageRequest = PageRequest.of(0, 3, Sort.Direction.DESC,"id");Page<User> page = userMapper.findAll(pageRequest);List<User> userList = page.getContent();return userList;
}

八 spring data jpa 自定义查询

关键字示例JPQL 表达式
AndfindByLastnameAndFirstname… where x.lastname = ?1 and x.firstname = ?2
OrfindByLastnameOrFirstname… where x.lastname = ?1 or x.firstname = ?2
Is, EqualsfindByFirstname, findByFirstnameIs, 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
IsNull, NullfindByAge(Is)Null… 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 ages)… where x.age not in ?1
TruefindByActiveTrue()… where x.active = true
FalsefindByActiveFalse()… where x.active = false
IgnoreCasefindByFirstnameIgnoreCase… where UPPER(x.firstame) = UPPER(?1)

例如:

public interface UserMapper extends JpaRepository<User,Integer> {List<User> findByIdLessThan(Integer id);List<User> findByNameLike(String keyword);
}

九 自定义sql

public interface UserMapper extends JpaRepository<User,Integer> {List<User> findByIdLessThan(Integer id);List<User> findByNameLike(String keyword);// 查询 id 最大的 user@Query(value = "select * from user where id = (select max(id) from user)",nativeQuery = true)User findUserByMaxId();// 自定义模糊查讯@Query(value = "select * from user where name like %:name%",nativeQuery = true)List<User> findUserNameByLike(@Param("name")String name);
}

十 复杂查询

  1. 一对一

    在实体类 配置 关联字段,其他不变

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @Entity(name = "student")
    public class Student {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Integer sid;@Column(name = "name")private String name;@Column(name = "age")private Integer age;@OneToOne// name 是本表字段  referencedColumnName 外表关联字段@JoinColumn(name = "gid",referencedColumnName = "gid")private Glass glass;
    }
    
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @Entity(name = "glass")
    public class Glass {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Integer gid;@Column(name = "gname")private String gname;
    }
    
  2. 一对多

    在 多端进行维护 如 一个班级有多个学生

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @Entity(name = "glass")
    public class Glass {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Integer gid;@Column(name = "gname")private String glassName;@OneToMany(mappedBy = "glass") // 设置 一对多 mapperBy 把自己交由 他表 进行维护private List<Student> studentList;}
    
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @EqualsAndHashCode(exclude = "glass") // jpa 使用lombok是需要 排除关联表属性
    @Entity(name = "student")
    public class Student {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Integer sid;@Column(name = "name")private String name;@Column(name = "age")private Integer age;@ManyToOne // 设置 多对一@JoinColumn(name = "gid")  // 外键 关联字段@JsonBackReference         // 避免 json回调关联private Glass glass;
    }
    
  3. 多对多

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @EqualsAndHashCode(exclude = "glass") // jpa 使用lombok是需要 排除关联表属性
    @Entity(name = "student")
    public class Student {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Integer sid;@Column(name = "name")private String name;@Column(name = "age")private Integer age;@ManyToMany// name : 中间表   joinColumns: 主表字段   inverseJoinColumns : 副表字段@JoinTable(name = "student_teacher",joinColumns = @JoinColumn(name = "sid"),inverseJoinColumns =  @JoinColumn(name ="tid"))private List<Teacher> teacherList;
    }
    
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @Entity(name = "teacher")
    public class Teacher {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Integer tid;@Column(name = "tname")private String tname;@Column(name = "tcourse")private String tcourse;}
    

一对一 和 多对多 只需要设置 一张表 ,而一对多 是双向关联的关系 需要设置 两张表(多端为 维护端)

十一 JpaSpecificationExcutor 的使用

​ 作用 : 封装 where 以后的查询方法 例如:

public interface StudentMapper extends JpaRepository<Student,Integer>, JpaSpecificationExecutor<Student> {}
@RequestMapping("select")
public List<Student> select(){Specification specification = new Specification<Student>() {@Overridepublic Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) {ArrayList<Predicate> predicateArrayList = new ArrayList<>();predicateArrayList.add(criteriaBuilder.equal(root.get("name"),"周弘杰"));predicateArrayList.add(criteriaBuilder.equal(root.get("age"),14));Predicate[] predicates = new Predicate[predicateArrayList.size()];return criteriaBuilder.and(predicateArrayList.toArray(predicates)); //  使用 and 查询 并返回}};return studentMapper.findAll(specification);
};

十二 JPQL

​ JPQL 全称java Persistence Query Language. 中文意思是 java 持久化查询语言

是一种可移植性查询语言,旨在以面向对象的表达式,将SQL语法和简单查询语义绑定在一起,使用这种语法编写的查询是 可移植性的,可以被编译所有主流数据库库服务器上的SQL

​ 其特征 与 原声的SQL 语句类似,并且完全面向对象,通过类名与属性访问,而不是 表名和表的属性

查询用的SELECT 语法如下:

比如 : select u from user u where u.userName :userName

User : 实体类名称 默认是 domain中的实体类名,如果使用了 注解@Entity(name=“”),则为name

u:别名

u.userName:实体对象的属性

:userName:是传递的参数

JPQL 语言不支持 增加操作,即 只有 delete,update ,select

public interface StudentMapper1 extends JpaRepository<Student,Integer>, JpaSpecificationExecutor<Student> {@Query("select s from student s where s.name=:name")List<Student> selectStudentByName(@Param("name") String name);
}

修改与删除

@Modifying // 默认为查询 设置为修改
@Transactional // 开启事务
@Query("update student s set s.name=:name where s.sid =:sid")
Integer updateStudentById(@Param("name") String name,@Param("sid") Integer sid);@Modifying
@Transactional
@Query("delete from student s where s.sid=:sid ")
Integer deleteStudentById(@Param("sid") Integer sid);

十三 基于jpa 配置多数据源

  1. 创建工程,添加Web,Jpa,MySql驱动,lombok依赖 ,druid

  2. 在 applicaiton.properties 中配置 数据源 与 jpa 相关配置

    # 数据库的基本配置
    spring.datasource.one.driver-class-name=com.mysql.jdbc.Driver
    spring.datasource.one.username=root
    spring.datasource.one.password=034312
    #注意多数据源要用jdbc-url
    spring.datasource.one.jdbc-url=jdbc:mysql://localhost:3306/boot1? characterEncoding=utf8&serverTimezone=GMT%2B8   
    spring.datasource.one.type=com.alibaba.druid.pool.DruidDataSourcespring.datasource.two.driver-class-name=com.mysql.jdbc.Driver
    spring.datasource.two.username=root
    spring.datasource.two.password=034312
    spring.datasource.two.jdbc-url=jdbc:mysql://localhost:3306/boot2?characterEncoding=utf8&serverTimezone=GMT%2B8
    spring.datasource.two.type=com.alibaba.druid.pool.DruidDataSource# JPA配置
    spring.jpa.properties.database=mysql
    spring.jpa.properties.show-sql=true
    spring.jpa.properties.hibernate.ddl-auto=update
    spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL57Dialect
    
  3. 配置DataSourceConfig:创建config 包,在包下 创建 DataSourceConfig

    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;@Configuration
    public class DataSourceConfig {@Bean@ConfigurationProperties(prefix = "spring.datasource.one")//这里添加@Primary注解,一定不能少,否则在项目启动时会出错,@Primary 表示当某一个类存在多个实例时,优先使用哪个实例@PrimaryDataSource dsOne() {return DataSourceBuilder.create().build();}@Bean@ConfigurationProperties(prefix = "spring.datasource.two")DataSource dsTwo() {return DataSourceBuilder.create().build();}
    }
    
  4. 在 config 下创建 JpaConfigOne 与 JpaConfigTwo

    import org.springframework.beans.factory.annotation.Autowired;
    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.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.annotation.Resource;
    import javax.sql.DataSource;
    @Configuration
    @EnableTransactionManagement
    @EnableJpaRepositories(basePackages = "com.zhj.mapper1",entityManagerFactoryRef = "entityManagerFactoryBeanOne",transactionManagerRef = "platformTransactionManagerOne")
    /*
    basePackages 用来指定 dao 所在的位置。
    entityManagerFactoryRef 用来指定实体类管理工厂 Bean 的名称
    transactionManagerRef 用来指定事务管理器的引用名称,
    默认的 Bean 名称为方法名*/
    public class JpaConfigOne {@Resource(name = "dsOne")DataSource dsOne;@AutowiredJpaProperties jpaProperties;@Bean@Primary//该 Bean 用来提供 EntityManager 实例LocalContainerEntityManagerFactoryBean entityManagerFactoryBeanOne(EntityManagerFactoryBuilder builder) {return builder.dataSource(dsOne) //配置数据源.properties(jpaProperties.getProperties())//设置 JPA 相关配置.packages("com.zhj.domain")//设置实体类所在的位置.persistenceUnit("pu1")//配置持久化单元名。若项目中只有一个 EntityManagerFactory,则 persistenceUnit 可以省略掉,若有多个,则必须明确指定持久化单元名。.build();}//创建一个事务管理器。JpaTransactionManager 提供对单个 EntityManagerFactory 的事务支持,专门用于解决 JPA 中的事务管理@BeanPlatformTransactionManager platformTransactionManagerOne(EntityManagerFactoryBuilder builder) {LocalContainerEntityManagerFactoryBean factoryBeanOne= entityManagerFactoryBeanOne(builder);return new JpaTransactionManager(factoryBeanOne.getObject());}}
    

    类似的创建 JpaConfigTwo,注意 去掉 @Primary

  5. 然后 建立相关的mapper 包 ,正常创建 mapper 类即可

更多推荐

springboot(MyBatis多数据源配置与JPA)

本文发布于:2024-03-23 23:22:33,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1744062.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:springboot   MyBatis   JPA

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!