5 SpringBoot 整合 tk

编程入门 行业动态 更新时间:2024-10-23 19:18:44

5 <a href=https://www.elefans.com/category/jswz/34/1769943.html style=SpringBoot 整合 tk"/>

5 SpringBoot 整合 tk

SpringBoot 整合 tk_Mybatis

1 简介

  上一节进行 SpringBoot 整合 Mybatis,若想更加快速开发,则使用 tk_MybatisMybatis-Plus 等 Mybatis 的工具。以下介绍 tk_Mybatis。为了方便学习,将上一节中的实体类、 mapper 接口和 mapper.xml 先删除。

  tk.mybatis 是在 MyBatis 框架的基础上提供了很多工具,让开发更加高效。

2 引入依赖

  在 pom.xml 文件中引入 mapper-spring-boot-starter 依赖,该依赖会自动引入 MyBaits 相关依赖。因此可以将上一节中的 Mybatis 依赖和 application.yml 中的 mybatis 配置去掉。

  添加 tk_mybatis 依赖,如下:

<dependency><groupId>tk.mybatis</groupId><artifactId>mapper-spring-boot-starter</artifactId><version>2.1.4</version>
</dependency>
3 创建通用父级接口

  在 java 文件下创建 tk.mybatis.mapper 包,然后创建 MyMapper 接口。主要作用是让 mapper 层的接口继承该接口,以达到使用 tk.mybatis 的目的。

  特别注意的是,该接口不可被扫描到,否则会出错。而之前在 HelloSpringBootApplication 启动类中配置的扫描路径是 com.pky.hello.springboot 包下的所有文件。

  因此只需将该接口所在的包和 com.pky.hello.springboot 同级即可,如图 3.1 所示:
      
              图 3.1

3.1 MyMapper 接口

package tk.mybatis.mapper;import tk.mybatis.mappermon.Mapper;
import tk.mybatis.mappermon.MySqlMapper;/*** 自己的 Mapper* 特别注意,该接口不能被扫描到,否则会出错*/
public interface MyMapper<T> extends Mapper<T>, MySqlMapper<T> {
}

3.2 HelloSpringbootApplication 启动类

package com.pky.hello.springboot;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import tk.mybatis.spring.annotation.MapperScan;@SpringBootApplication(scanBasePackages = "com.pky.hello.springboot") //将所有基于该包名进行扫描
@MapperScan(basePackages = "com.pky.hello.springbootmons.mapper")  //指定扫描 mapper,避免扫描到 tk.mybatis.mapper 包的接口
public class HelloSpringbootApplication {public static void main(String[] args) {SpringApplication.run(HelloSpringbootApplication.class, args);}
}
4 自动代码生成

4.1 介绍

  在开发过程中,我们需要些很多实体类,其实我们并不需花费时间在这上面。

  因此我们使用 MyBatis 的 Maven 插件生成代码,这样我们无需手动编写实体类MapperMapper.xml 配置文件,只需要使用 MyBatis 提供的一个 Maven 插件就可以自动生成所需的各种文件便能够满足基本的业务需求,如果业务比较复杂只需要修改相关文件即可。

4.2 插件

  在 pom.xml 中添加插件

<plugin><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-maven-plugin</artifactId><version>1.3.5</version><configuration><configurationFile>${basedir}/src/main/resources/generator/generatorConfig.xml</configurationFile><overwrite>true</overwrite><verbose>true</verbose></configuration><dependencies><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.35</version></dependency><!-- 这里采用了 tk_mybatis,若不想要则去掉 --><dependency><groupId>tk.mybatis</groupId><artifactId>mapper</artifactId><version>4.1.4</version></dependency></dependencies>
</plugin>

configurationFile:自动生成代码的配置文件路径

4.3 generatorConfig.xml 配置文件

  创建自动生成代码的配置文件,在 resources 中创建 generator,并在 generator 下创建配置类 generatorConfig.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfigurationPUBLIC "-//mybatis//DTD MyBatis Generator Configuration 1.0//EN"".dtd"><generatorConfiguration><!-- 引入数据库连接配置 --><properties resource="jdbc.properties"/><context id="Mysql" targetRuntime="MyBatis3Simple" defaultModelType="flat"><property name="beginningDelimiter" value="`"/><property name="endingDelimiter" value="`"/><!-- 配置 tk.mybatis 插件 --><plugin type="tk.mybatis.mapper.generator.MapperPlugin"><property name="mappers" value="tk.mybatis.mapper.MyMapper"/></plugin><!-- 配置数据库连接 --><jdbcConnectiondriverClass="${jdbc.driverClass}"connectionURL="${jdbc.connectionURL}"userId="${jdbc.username}"password="${jdbc.password}"></jdbcConnection><!-- 配置实体类存放路径 --><javaModelGenerator targetPackage="com.pky.springbootdemomons.domain" targetProject="src/main/java"/><!-- 配置 XML 存放路径 --><sqlMapGenerator targetPackage="mapper" targetProject="src/main/resources"/><!-- 配置 DAO 存放路径 --><javaClientGeneratortargetPackage="com.pky.springbootdemomons.mapper"targetProject="src/main/java"type="XMLMAPPER"/><!-- 配置需要指定生成的数据库和表,tb_user 是表名,可用 % 代替,表示全部表 --><table catalog="myshop" tableName="tb_user"><!-- mysql 配置 --><generatedKey column="id" sqlStatement="Mysql" identity="true"/></table></context>
</generatorConfiguration>

注意:若该配置头中的“.dtd” 报错,则点击左边红色灯泡里选项的第一项即可。

4.4 jdbc.properties 数据库连接配置

  在 resources 中创建 jdbc.properties,用于 generatorConfig.xml 数据库连接的配置信息。

jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.connectionURL=jdbc:mysql://localhost:3306/myshop?useUnicode=true&characterEncoding=utf-8&useSSL=false
jdbc.username=root
jdbc.password=root

4.5 自动代码生成

  • 点即 IDEA 右边的 Maven Project,如图 4.1 操作双击选项

                  图 4.1

  • 代码生成成功则会在控制台显示如图 4.2 所示信息

                  图 4.2

  • 此时,会在相应目录下看到生成的实体类 TbUsr、Mapper 接口 TbUserMapper 和 TbUserMapper.xml,如下图 4.3 所示

              图 4.3

提示:查看实体类中的@Table(name = “myshop.tb_user”)是否正确

5 tk_mybatis 的使用

  既然用上了 tk_mybatis,自然要知道如何使用,如何提高开发效率。

  tk_mybatis 有好几种方式:

  • 普通Example方式(从and方法开始可以实现动态sql拼接)
  • Criteria方式(可使用criteria完成动态sql拼接)
  • Example.builder 方式(其中where从句中内容可以拿出来进行动态sql拼接)
  • Example.builder + Weekend方式

  下面介绍 Exxample 方式,如下

5.1 例子

Example example = new Example(CandidateBrandEntity.class);
example//.selectProperties("cabId","cabName").and().andEqualTo("cabDeleted",0).andLike("cabName","%d%");// 排序
example.orderBy("cabCreatedTime")/*.desc()*/.orderBy("cabId").desc();// 获得结果
List<CandidateBrandEntity> brands = brandEntityMapper.selectByExample(example);

5.2 LoginServiceImpl

  根据 5.1 的例子,我们完善登录的业务处理。

package com.pky.hello.springbootmons.service;import com.pky.hello.springbootmons.domain.TbUser;
import com.pky.hello.springbootmons.mapper.TbUserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import tk.mybatis.mapper.entity.Example;/*** 登录业务逻辑*/
@Service
public class LoginServiceImpl implements LoginService {@AutowiredTbUserMapper tbUserMapper;/*** 通过用户名获取登录用户信息* @param tbUser* @return*/@Overridepublic TbUser getByLoginId(TbUser tbUser) {Example example = new Example(TbUser.class);// "username" 与实体类属性对应example.createCriteria().andEqualTo("username", tbUser.getUsername());TbUser user = tbUserMapper.selectOneByExample(example);boolean flag = false;// 查询成功if(user != null) {// 判断密码flag = checkPassword(user, tbUser.getPassword());}// 登录成功if(flag) {return user;}// 登录失败return null;}/*** 判断密码* @param tbUser* @param loginPwd 登录密码* @return*/private Boolean checkPassword(TbUser tbUser, String loginPwd) {// 因数据库中的密码是 md5 加密,因此需要将登录密码进行加密后比较String password = DigestUtils.md5DigestAsHex(loginPwd.getBytes());// 密码正确if(tbUser.getPassword().equals(password)) {return true;}return false;}
}

5.3 LoginController

  目前我们写的是 JSON API 接口,因此需要添加 JSON 依赖。

<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId><version>2.9.7</version>
</dependency>
<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.28</version>
</dependency>

在实体类上添加 @JsonInclude(JsonInclude.Include.NON_NULL) ,表示属性为 NULL 不序列化

  并且还要做参数的数据校验,因此添加数据校验的依赖以及工具类。

  • 依赖
<!-- 数据校验 -->
<dependency><groupId>org.hibernate.validator</groupId><artifactId>hibernate-validator</artifactId>
</dependency>

在实体类属性上添加校验规则,如下:

/*** 用户名*/
@NotNull(message = "用户名不可为空")
private String username;/*** 密码,加密存储*/
@NotNull(message = "密码不可为空")
@JsonIgnore // 密码不进行序列化,即不返回修饰的属性
private String password;
  • 数据校验工具类,在 commons 包下创建 utils 包,再在 utils 包下创建数据校验工具类 BeanValidator
package com.pky.hello.springbootmons.utils;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.Validator;
import java.util.*;/*** JSR303 Validator(Hibernate Validator)工具类.* <p>* ConstraintViolation 中包含 propertyPath, message 和 invalidValue 等信息.* 提供了各种 convert 方法,适合不同的 i18n 需求:* 1. List<String>, String 内容为 message* 2. List<String>, String 内容为 propertyPath + separator + message* 3. Map<propertyPath, message>* <p>* 详情见wiki: ** <p>Title: BeanValidator</p>* <p>Description: </p>** @author PKY* @version 1.0.0* @date 2018/5/26 17:21*/
@Component
public class BeanValidator {@Autowiredprivate Validator validatorInstance;private static Validator validator;@PostConstruct  //Spring 启动时,直接执行修饰的方法public void init() {BeanValidator.validator = validatorInstance;}/*** 调用 JSR303 的 validate 方法, 验证失败时抛出 ConstraintViolationException.*/private static void validateWithException(Validator validator, Object object, Class<?>... groups) throws ConstraintViolationException {Set constraintViolations = validator.validate(object, groups);if (!constraintViolations.isEmpty()) {throw new ConstraintViolationException(constraintViolations);}}/*** 辅助方法, 转换 ConstraintViolationException 中的 Set<ConstraintViolations> 中为 List<message>.*/private static List<String> extractMessage(ConstraintViolationException e) {return extractMessage(e.getConstraintViolations());}/*** 辅助方法, 转换 Set<ConstraintViolation> 为 List<message>*/private static List<String> extractMessage(Set<? extends ConstraintViolation> constraintViolations) {List<String> errorMessages = new ArrayList<>();for (ConstraintViolation violation : constraintViolations) {errorMessages.add(violation.getMessage());}return errorMessages;}/*** 辅助方法, 转换 ConstraintViolationException 中的 Set<ConstraintViolations> 为 Map<property, message>.*/private static Map<String, String> extractPropertyAndMessage(ConstraintViolationException e) {return extractPropertyAndMessage(e.getConstraintViolations());}/*** 辅助方法, 转换 Set<ConstraintViolation> 为 Map<property, message>.*/private static Map<String, String> extractPropertyAndMessage(Set<? extends ConstraintViolation> constraintViolations) {Map<String, String> errorMessages = new HashMap<>();for (ConstraintViolation violation : constraintViolations) {errorMessages.put(violation.getPropertyPath().toString(), violation.getMessage());}return errorMessages;}/*** 辅助方法, 转换 ConstraintViolationException 中的 Set<ConstraintViolations> 为 List<propertyPath message>.*/private static List<String> extractPropertyAndMessageAsList(ConstraintViolationException e) {return extractPropertyAndMessageAsList(e.getConstraintViolations(), " ");}/*** 辅助方法, 转换 Set<ConstraintViolations> 为 List<propertyPath message>.*/private static List<String> extractPropertyAndMessageAsList(Set<? extends ConstraintViolation> constraintViolations) {return extractPropertyAndMessageAsList(constraintViolations, " ");}/*** 辅助方法, 转换 ConstraintViolationException 中的 Set<ConstraintViolations> 为 List<propertyPath + separator + message>.*/private static List<String> extractPropertyAndMessageAsList(ConstraintViolationException e, String separator) {return extractPropertyAndMessageAsList(e.getConstraintViolations(), separator);}/*** 辅助方法, 转换 Set<ConstraintViolation> 为 List<propertyPath + separator + message>.*/private static List<String> extractPropertyAndMessageAsList(Set<? extends ConstraintViolation> constraintViolations, String separator) {List<String> errorMessages = new ArrayList<>();for (ConstraintViolation violation : constraintViolations) {errorMessages.add(violation.getPropertyPath() + separator + violation.getMessage());}return errorMessages;}/*** 服务端参数有效性验证** @param object 验证的实体对象* @param groups 验证组* @return 验证成功:返回 null;验证失败:返回错误信息*/public static String validator(Object object, Class<?>... groups) {try {validateWithException(validator, object, groups);} catch (ConstraintViolationException ex) {List<String> list = extractMessage(ex);list.add(0, "数据验证失败:");// 封装错误消息为字符串StringBuilder sb = new StringBuilder();for (int i = 0; i < list.size(); i++) {String exMsg = list.get(i);if (i != 0) {sb.append(String.format("%s. %s", i, exMsg)).append(list.size() > 1 ? "<br/>" : "");} else {sb.append(exMsg).append(list.size() > 1 ? "<br/>" : "");}}return sb.toString();}return null;}}
  • Controller
package com.pky.hello.springboot.controller;import com.alibaba.fastjson.JSONObject;
import com.pky.hello.springbootmons.domain.TbUser;
import com.pky.hello.springbootmons.service.LoginService;
import com.pky.hello.springbootmons.utils.BeanValidator;
import org.apachemons.lang3.StringUtils;
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.RestController;@RestController
@RequestMapping(value = "users")
public class LoginController {@AutowiredLoginService loginService;@GetMapping(value = "login")public JSONObject login(TbUser tbUser) {JSONObject jsonObject = new JSONObject();// 数据校验String message = BeanValidator.validator(tbUser);if(StringUtils.isNotBlank(message)) {jsonObject.put("msg", message);return jsonObject;}// 登录校验TbUser user = loginService.getByLoginId(tbUser);// 登录成功if(user != null) {jsonObject.put("msg", "登录成功!");jsonObject.put("tb_user", user);}// 登录失败else {jsonObject.put("msg", "用户名或密码错误!");}return jsonObject;}
}
6 结果
  • 成功结果,浏览器输入: http://localhost:8082/v1/hello_springboot/users/login?username=zhangsan&password=123456 ,如图 6.1 所示

                      图 6.1

  • 数据校验结果,浏览器输入: http://localhost:8082/v1/hello_springboot/users/login ,如图 6.2 所示

                    图 6.2

  • 账号密码错误,浏览器输入: http://localhost:8082/v1/hello_springboot/users/login?username=ceshi&password=123

                    图 6.3

  以上可以发现,我们并没有在 mapper 接口和 mapper.xml 中写相应的代码就可从数据库中获取数据。因为tk_mybatis 已经将 sql 封装好了,我们只需调用其相应 的方法即可。

7 附 tk_mybatis 的几种用法

7.1 Criteria方式(可使用criteria完成动态sql拼接)

  • 从代码语义来理解,先创建需要查询的实例
Example example = new Example(TbUser.class);
example.createCriteria().andEqualTo("username","zhangsan");
TbUser tbUser = tbUserMapper.selectOneByExample(example);
System.out.println(tbUser.getId());
  • 模糊查询及排序
Example example = new Example(TbUser.class);
example.createCriteria().andLike("username","%zhang%");
example.orderBy("created").desc();
List<TbUser> tbUsers = tbUserMapper.selectByExample(example);
tbUsers.forEach(tbUser -> System.out.println(tbUser.getUsername()));
  • 自定义 mapper,如多表联查,和之前写 MyBatis 时一样,在xxxMapper.xml 中
<select id="selectById" resultType="com.pky.spring.boot.login.domain.TbItemDesc">SELECTb.item_desc AS 'itemDesc'FROMtb_item AS aLEFT JOIN tb_item_desc AS bON a.id = b.item_idWHERE a.id = #{id}
</select>

注意:自定义的话还需要在 mapper 对应的接口上写对应的注解代码,如下:

package com.pky.springbootdemomons.mapper;import com.pky.springbootdemomons.domain.TbUser;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;
import tk.mybatis.mapper.MyMapper;@Repository
public interface TbUserMapper extends MyMapper<TbUser> {/*** 自定义的需要写相应的注解,并且括号内容和 XML 的一致* @param username* @return*/@Select("Select * from tb_user where username = #{username}")TbUser getByLoginId(String username);
}

7.2 Example.builder 方式(其中where从句中内容可以拿出来进行动态sql拼接)

Example example = Example.builder(MybatisDemo.class).select("cabId","cabName").where(Sqls.custom().andEqualTo("count", 0).andLike("name", "%d%")).orderByDesc("count","name").build();
List<MybatisDemo> demos = mybatisDemoMapper.selectByExample(example);

7.3 Example.builder + Weekend方式

  • 优势:不用输入属性名,避免数据库有变动或输入错误就会出错
//获得seekendsql
WeekendSqls<MybatisDemo> sqls = WeekendSqls.<MybatisDemo>custom();//可进行动态sql拼接
sqls = sqls.andEqualTo(MybatisDemo::getCount,0).andLike(MybatisDemo::getName,"%d%");//获得结果
List<MybatisDemo> demos = mybatisDemoMapper.selectByExample(Example.builder(MybatisDemo.class).where(sqls).orderByDesc("count","name").build());

7.4 参考地址

.example

SpringBoot 整合 Mybatis <<                 >> 通用 JSON API

更多推荐

5 SpringBoot 整合 tk

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

发布评论

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

>www.elefans.com

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