欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

数据库访问中间件

程序员文章站 2022-06-25 17:13:40
数据库访问中间件SpringBoot整合MyBatisSpringBoot整合MyBatisMybatis回顾...

SpringBoot整合MyBatis

Mybatis回顾

一、配置

MyBatis的配置

	设置mybatis的配置文件路径,默认是在resources的目录
mybatis.config-location=classpath:mybatis/mybatis-config.xml
	设置mybatis下面的mapper映射文件路径,默认是在resources的目录
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml
	设置项目中实体类包路径;
mybatis.type-aliases-package=com.study.springbootmybatis.entity
	设置缓存失效
spring.thymeleaf.cache=false
	展示sql语句
logging.level.com.study.springbootmybatis.repository.UsersDao=debug

测试

@SpringBootTest
class SpringbootMybatisApplicationTests {
    @Resource
    UsersDao usersDao;
    @Test
    void contextLoads() {
        System.out.println(usersDao.findAll());
    }
}

注解

public interface UsersDao {
	非注解,在mapper中配置
    List<Users> findAll();
    Users findById(int id);
    注解
    @Select("select id,username,password,name from users where name like #{name}")
    Users findByName(String name);

}

零配置

在properties中删除相关xml配置,删除实体类路径。
在资源中删除xml文件
在dao接口中删除非注解方法。

Springboot结合rest和mybatis完成业务操作

	这里是演示一对多中的多
    @Select("select * from Product where uid=#{uid}")
    Product findByUid(int uid);
演示一对多中的1,这里是根据id来查users对象,那么我们可以结合ProductRepository来一次性把对应的product也查出来
property指的是在Users实体类中一对多中的多的属性名,column代表的是把users表中的那个字段作为后面查询的条件,many指的是查询是一对多还是一对一
    @Select("select * from Users where id=#{id}")
    @Results({
            @Result(
                    property = "products",column = "id",many = @Many(select = "com.study.springbootmybatis.repository.ProductRepository.findByUid")
            )
    })
    Users findUsersById(int id);

Spring Data Jpa 的简介和快速入门

一、Spring Data

简介

Spring Data是为了简化构建基于Spring框架应用的数据访问技术。包括对关系数据库、非关系数据库、Map-Reduce框架、云数据服务等访问支持。它为我们提供使用统一的API标准来对数据访问层进行操作,这套标准包含了CRUD(创建、获取、更新、删除)、查询、排序和分页的相关操作。

特点

  • 支持对象关系映射:
    • 具备ORM框架的对象关系映射功能
  • 统一的Repository接口
    • Repository<T,ID extends Serializable>: 统一接口
    • CrudRepository<T,ID extends Serializable> 基本CRUD操作
    • PagingAndSortingRepository<T,ID> extends Serializable>:基本CRUD及分页
  • 统一的数据访问模板类xxxTemplate
    • 如:MongoTemplate、RedisTempIate等

二、JPA

简介

  • Jpa是 java持久化规范,它为Java开发人员提供一种对象/关联映射工具来管理Java应用中的关系数据。它的出现主要是为了简化现有的持久化开发工作和整合ORM技术,结束现在Hibernate、TopLink、JDO等ORM框架各自为营的局面
  • Jpa是在充分吸收了现有的Hibernate、TopLink、JDO等ORM框架的基础上发展而来的,具有易于使用、伸缩性强等优点。
  • JPA是一套规范,不是一套产品,那么像Hibernate、TopLink、JDO它们是一套产品,如果说这些产品实现了这个JPA规范,那么我们就可以称他们为JPA的实现产品。

:jdbc是数据访问规范

Spring Data 与 JPA 的关系

数据库访问中间件

Spring Data JPA 工作原理

数据库访问中间件

快速入门

jpa配置

spring:
  jpa:
    show-sql: true  //支持sql输出
    database: mysql  //数据库类型
    hibernate:
      ddl-auto: update  //自动生成开启,让表数据会自动跟随entity类的变化而变化
    properties:
      hibernate:
        format_sql: true   //format一下SQL进行输出
    database-platform:  org.hibernate.dialect.MySQL5InnoDBDialect

repository

public interface UserRepository extends JpaRepository<TUser, Integer> {
    TUser findTuserByUsernameLike(String username);
}

Spring Data JPA 的基本使用

一、基于单表的SQL操作

单表SQL操作-使用关键字拼凑方法

关键词 样例 JPQL代码段
And findByLastnameAndFirstname … where x.lastname = ?1 and x.firstname = ?2
Or findByLastnameOrFirstname … where x.lastname = ?1 or x.firstname = ?2
Is,Equals findByFirstname,findByFirstnameIs,findByFirstnameEquals … where x.firstname = ?1
Between findByStartDateBetween … where x.startDate between ?1 and ?2
LessThan findByAgeLessThan … where x.age < ?1
LessThanEqual findByAgeLessThanEqual … where x.age <= ?1
GreaterThan findByAgeGreaterThan … where x.age > ?1
GreaterThanEqual findByAgeGreaterThanEqual … where x.age >= ?1
After findByStartDateAfter … where x.startDate > ?1
Before findByStartDateBefore … where x.startDate < ?1
IsNull findByAgeIsNull … where x.age is null
IsNotNull,NotNull findByAge(Is)NotNull … where x.age not null
Like findByFirstnameLike … where x.firstname like ?1
NotLike findByFirstnameNotLike … where x.firstname not like ?1
StartingWith findByFirstnameStartingWith … where x.firstname like ?1(附加参数绑定%)
EndingWith findByFirstnameEndingWith … where x.firstname like ?1(与前置绑定的参数%)
Containing findByFirstnameContaining … where x.firstname like ?1(包含参数绑定%)
OrderBy findByAgeOrderByLastnameDesc … where x.age = ?1 order by x.lastname desc
Not findByLastnameNot … where x.lastname <> ?1
In findByAgeIn(Collection ages) … where x.age in ?1
NotIn findByAgeNotIn(Collection ages) … where x.age not in ?1
TRUE findByActiveTrue() … where x.active = true
FALSE findByActiveFalse() … where x.active = false
IgnoreCase findByFirstnameIgnoreCase … where UPPER(x.firstame) = UPPER(?1)

示例

1、查询出年龄小于等于22岁的人;
    List<Person> findAllByPageIsLessThanEqual(Integer age);
2、查询出年龄在20-22岁之间并且性别是男的人
    List<Person> findAllByPageBetweenAndPsexEquals(Integer lowage,Integer highage,String sex);
3、查询出已经结婚并且性别是男的人
    List<Person> findAllByGetmarriedIsTrueAndPsexEquals(String psex);
  • 实体类属性名不要出现is×xx、get)(xx的名称,会导致关键字拼凑出错
  • 实体类属性名中间只要出现了大写字母,就会导致数据库的字段名有下划线隔开,比如你使
  • 用isMarried属性名,那么实体类的字段名就会变成is一married,这样容易导致找不到值
  • 属性名类型是b[ean类型的在某些数据库中会变成bit(1)类型,其中0为false,1为true
    实体类
@Data
@Entity
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Person {
    @Id
    @GenericGenerator(name = "myuuid",strategy = "uuid") 主键生成策略
    @GeneratedValue(generator = "myuuid")
    private String pid;
    @Column(unique = true)
    private String pname;
    @Column
    private String psex;
    @Column
    private Integer page;
    @Column
    private boolean getmarried;
}

关键拼凑字无法解决的问题

  • 实体类的是属性名与表的字段名无法映射,导致关键字找不到
  • CRUD操作方式比较另类或者是你不想用关键字的写法
  • 涉及到了多表操作

使用注解手写sql语句

  • 使用SQL语句来书写SQL
  • 使用HQL语句来书写SQL

相关操作

  • 按照pname来模糊删除
  • 查询出年龄是20.22岁的并且性别是女的人
  • 使用spe[表达式来演示用户的登陆

注意事项

  • 如果是删改操作,需要加@Modifying和@Transactional注解
  • 如果是SQL语句,请在@Query注解上加上NativeQuery=true的属性
  • 传参的方式有两种:
    • 使用?+数字的方式,数字从1开始,代表第几个参数
    • 使用:+参数名的方式,这种方式最好配合@Param注解一起使用

示例

    @Transactional
    @Modifying
   /示例1 @Query(value = "delete from Person where pname like ?1")  1代表匹配第一个参数
    void deleteByName(String pname);/
    或者这样↓  推荐使用这种
   /示例2 @Query(value = "delete from Person where pname like :pname")
    void deleteByName(@Param("pname")String pname); /
   示例3 @Query(value = "delete from Person where pname like %:pname%")
    void deleteByName(@Param("pname")String pname);


   默认是HQL语句,如果打sql语句需要多一个变量
    /@Query(value = "select * from person where page between 20 and 22 and psex='女',",nativeQuery = true)/
    @Query(value = "select p from Person p where p.page between 20 and 22 and p.psex='女'")
    List<Person> findPerson();


 	使用SPEL表达式来完成person表的修改操作
    @Modifying
    @Transactional
    @Query(value = "update person set pname=:#{#person.pname},psex=:#{#person.psex},page=:#{#person.page} where pid=:#{#person.pid}",nativeQuery = true)
    void updatePerson(@Param("person")Person person);

二、JPA逆向工程及多表SQL操作

  • 使用数据接口
    • 构建一个数据接口,里面的抽象方法就是SQL语句的查询结果的字段对应的getXXX的抽象方法。
  • 使用集合 (推荐)
    • 直接使用List/Map等集合嵌套的方式来获取到接收数据
  • 使用VO(view object)
    • 单独构建一个跟页面展示数据对应的VO的实体类来接接收数据

利用idea右侧数据库工具连接上数据库
利用Jpa生成实体类

  • project structure - > Modules -> 点击“+” -> 选择Jpa, -> 点击右侧“+” -> 选择第一个persistence.xml。-> 点击ok
  • 在界面左侧出现persistence 标题卡 选择唯一的那个项目,右键选择Generate persistence Mapping -> 选择By DataSource Schema ,选择数据库,选择实体类生成所在的包。为想要生成table打上勾,实体类前缀 后缀为空。最后选择yes。

示例

    联表查询-根据书名来查该书籍的拥有者
    @Query(value = "select p from Person p inner join Book b on p.pid=b.pid where b.bname=:bname")
    Person findPersonByBname(@Param("bname") String bname);

    联表查询-根据用户id来查询person和book  (通过数据接口的方式)
    @Query(value = "select p.pid as pid, p.pname as pname, p.psex as psex, p.getmarried as getmarried," +
            "b.bid as bid,b.bname as bname, b.bprice as bprice from Person p inner join Book b on p.pid =b.pid " +
            "where p.pid=:pid")
    List<PersonInfo> findAllInfo(@Param("pid") String pid);

    联表查询-根据用户id来查询person和book  (通过简单集合的方式)
    @Query(value = "select p.pid as pid, p.pname as pname, p.psex as psex, p.getmarried as getmarried," +
            "b.bid as bid,b.bname as bname, b.bprice as bprice from Person p inner join Book b on p.pid =b.pid " +
            "where p.pid=:pid")
    List<Object> findAllInfo1(@Param("pid") String pid);

    联表查询-根据用户id来查询person和book  (通过嵌套集合的方式)
    @Query(value = "select p.pid as pid, p.pname as pname, p.psex as psex, p.getmarried as getmarried," +
            "b.bid as bid,b.bname as bname, b.bprice as bprice from Person p inner join Book b on p.pid =b.pid " +
            "where p.pid=:pid")
    List<Map<String, Object>> findAllInfo2(@Param("pid") String pid);

上述示例用到的数据接口

public interface PersonInfo { //数据接口
    String getPid();
    String getPname();
    String getPsex();
    String getPage();
    String getGetmarried();
    Integer getBid();
    String getBname();
    double getBprice();
}

测试


		数据接口的方式 
		List<PersonInfo> allInfo = personRepository.findAllInfo("40280981727e7c0401727e7c11210002");
        for (PersonInfo info : allInfo) {
            System.out.println(info.getPid()+","+ info.getPname() +","+ info.getPsex() +","+ info.getPage()  +
                    ","+ info.getGetmarried() +","+ info.getBid() +","+ info.getBname() +","+ info.getBprice() );
        }
        简单集合的方式
        List<Object> allInfo1 = personRepository.findAllInfo1("40280981727e7c0401727e7c11210002");
        Object[] o =(Object[]) allInfo1.get(0);
        System.out.println(Arrays.toString(o));/

        嵌套集合的方式 List<Map>
        System.out.println(personRepository.findAllInfo2("40280981727e7c0401727e7c11210002"));

注: 多表SQL操作注意事项
- 使用数据接口的方式来接受查询的字段时要注意,必须要为要查询的字段名起别名,否则会无法取到

三、 QueryDSL的简单介绍

简介

  • QueryDSL仅仅时一个通用的查询框架,专注于通过JavaAPI构建类型安全的Sql查询,也可以说QueryDSL是基于各种ORM框架以及Sql之上的一个通用的查询框架,QueryDSL的查询,类似于SQL查询,很全面只不过一个是用SQL一个是用代码来代替SQL

建议

  • 建议 单表乃至简单的多表操作,都不推荐使用QueryDSL‘,使用JPA自带API简介又效率,但是涉及太复杂的查询,推荐使用QueryDSL

QueryDSL官网
操作总结:
数据库访问中间件

Springboot中的分页

使用JPA自带的Pageable接口分页

Pageable

简介

Pageable分页是SpringDataJPA默认提供的分页功能,直接继承JpaRepository就获得了该分页功能;

分页模型

First Previous 1 2 3 4 5 6 Next Last
  • 获取元素总数;
  • 获取总页数;
  • 获取当前页数;
  • 获取当前页的内容;
  • 是否有上一页、上一页;
  • 是否有下一页、下一页的内容;
  • 首页、尾页的内容;

使用Mybatis和PageHelper插件进行分页

两种分页的区别

本文地址:https://blog.csdn.net/Mr_ZHOUZHOU/article/details/107385903