当前位置: 移动技术网 > IT编程>开发语言>Java > 数据库访问中间件

数据库访问中间件

2020年07月18日  | 移动技术网IT编程  | 我要评论

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


操作总结:
在这里插入图片描述

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

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网