MyBatis 初步(mybatis 教程)

  本篇文章为你整理了MyBatis 初步(mybatis 教程)的详细内容,包含有mybatis startwith mybatis 教程 mybatis快速入门 mybatis入门程序 MyBatis 初步,希望能帮助你了解 MyBatis 初步。

  MyBatis 初步

  目前我对 MyBatis 的了解不是很深,停留在企业比较常用的"数据库框架"上,系统性的学习要看官方文档。

  这篇随笔主要围绕 SpringBoot 中 gradle 环境的搭建来讲,是我从《深入浅出SpringBoot2》中讨的一些知识。

  可以跟着文章做一个基础环境的项目。

  仓库地址:mvnrepository 和 阿里云

  因为用的 gradle ,在 build.gradle 中的 dependencies 中加入依赖包:

  

implementation org.mybatis.spring.boot:mybatis-spring-boot-starter:2.2.2

 

  implementation org.springframework.boot:spring-boot-starter-web

  implementation mysql:mysql-connector-java:8.0.29

  

 

  创建数据表和插入数据

  终端进入 MySQL 中 xxx 数据库,输入 SQL 语句:

  

CREATE TABLE t_user(

 

   id INT(12) NOT NULL AUTO_INCREMENT,

   user_name VARCHAR(60) NOT NULL,

   sex INT(3) NOT NULL DEFAULT 1 CHECK (sex in (1,2)),

   note VARCHAR(256) NULL,

   PRIMARY KEY(id)

  

 

  

 INSERT INTO t_user(id,user_name,note) VALUES(1,"user_name_1","zhangsan");

 

  

 

  创建实体类并设置别名

  因为类的全限定名很长,所以使用 @Alias(value = "xxx") 的方式,一般用来和数据表属性相对的类上(实体类)。

  数据表与之对应的实体类如下(自行加入 getter 和 setter ):

  

package mybatis.pojo;

 

  import mybatis.enumeration.SexEnum;

  import org.apache.ibatis.type.Alias;

   * @author enrace

   * @Alias MyBatis give the class other name.

  @Alias(value = "user")

  public class User {

   private Long id = null;

   private String userName = null;

   private String note = null;

   * The sex is numeration here need use typeHandler to switch.

   private SexEnum sex = null;

   public User() {}

   /** setter 和 getter 方法自行加入即可 **/

  

 

  创建enum 枚举类型和 typeHandler

  typeHandler 是 MyBatis 的重要配置之一,用于不同类型的数据进行自定义转换。

  我学习了将 Java 中的 enum (枚举类)的实例和数据库的 int 进行转换。

  先看看 enum 的使用,enum 的代码如下(自行加入 getter 和 setter ):

  

package mybatis.enumeration;

 

   * @author enrace

  public enum SexEnum {

   MALE(1, "男"),

   FEMALE(2,"女");

   private int id;

   private String name;

   SexEnum(int id, String name) {

   this.id = id;

   this.name = name;

   public static SexEnum getEnumById(int id) {

   for (SexEnum sex : SexEnum.values() ) {

   if (sex.getId() == id) {

   return sex;

   return null;

   /** setter 和 getter 方法自行加入即可 **/

  

 

  enum 中有两个类型 MALE 和 FEMALE 分别对应 MySQL 中 int 的 1 和 2。

  其中的 getEnumById() 的方法是通过接收 int 返回 enum 的实例。

  接着说说 typeHandler,这是通过继承的方式自定以了一个 typeHandler:

  

package mybatis.typehandler;

 

  import mybatis.enumeration.SexEnum;

  import org.apache.ibatis.type.BaseTypeHandler;

  import org.apache.ibatis.type.JdbcType;

  import org.apache.ibatis.type.MappedJdbcTypes;

  import org.apache.ibatis.type.MappedTypes;

  import java.sql.CallableStatement;

  import java.sql.PreparedStatement;

  import java.sql.ResultSet;

  import java.sql.SQLException;

   * @MappendJdbcTypes Declare JdbcType to be an integer.

   * @author enrace

  @MappedJdbcTypes(JdbcType.INTEGER)

  @MappedTypes(value = SexEnum.class)

  public class SexTypeHandler extends BaseTypeHandler SexEnum {

   * Read gender by column name.

   @Override

   public SexEnum getNullableResult(ResultSet rs, String col) throws SQLException {

   int sex = rs.getInt(col);

   if(sex != 1 sex != 2) {

   return null;

   return SexEnum.getEnumById(sex);

   * Read gender by subscript.

   * @param rs

   * @param idx

   * @return SexEnum

   * @throws SQLException

   @Override

   public SexEnum getNullableResult(ResultSet rs, int idx) throws SQLException{

   int sex = rs.getInt(idx);

   if (sex != 1 sex != 2) {

   return null;

   return SexEnum.getEnumById(sex);

   * Read gender from a stored procedure.

   * @param cs

   * @param idx

   * @return SexEnum

   * @throws SQLException

   @Override

   public SexEnum getNullableResult(CallableStatement cs, int idx) throws SQLException {

   int sex = cs.getInt(idx);

   if (sex != 1 sex != 2) {

   return null;

   return SexEnum.getEnumById(sex);

   * Set not null gender parameter.

   * @param ps

   * @param idx

   * @param sex

   * @param jdbcType

   * @throws SQLException

   @Override

   public void setNonNullParameter(PreparedStatement ps, int idx, SexEnum sex, JdbcType jdbcType)

   throws SQLException {

   ps.setInt(idx, sex.getId());

  

 

  这个类的几种方法,主要是通过 enum.getEnumById() 返回一个 enum 类型的结果。

  我将 SexTypeHandler 分成简述和细述:

  简叙:

  网上了解的是: 一个 setxxx 方法,表示向 PreparedStatement 里面设置值。三个 getxxx 方法,一个是根据列名获取值,一个是根据列索引位置获取值,最后一个是存储过程。

  细述:

  ResultSet 类型我去查了一下,表示数据库结果集的数据表,其中的 getXXX 表示在结果集中检索 XXX 类型。

  ResultSet.getInt(col) 方法通过 SQL 子句中指定的列的标签获取 sex 的 int。

  ResultSet.getInt(idx) 方法通过第几列的方式从数据表中获取 sex 的 int。

  CallableStatement 类型可以返回一个对象或多个对象ResultSet。

  网上了解到 CallableStatement 类型用于从Java程序调用存储过程,存储过程是我们在数据库中为某些任务编译的一组语句。 当我们处理具有复杂场景的多个表时,存储过程是有益的,而不是向数据库发送多个查询,我们可以将所需的数据发送到存储过程,并在数据库服务器本身中执行逻辑。

  自己不是很明白存储过程,不过 CallableStatement 可以获取到结果,自然能获取到我们需要的 int 类型。

  cs.getInt(idx) 方法通过传入的 int 检索指定JDBC INT类型的值。

  ps.setInt(idx, sex.getId()) 设置给定的 java int 指定参数值。驱动将一个 SQL INTEGER 值发送到数据库。

  定义 MyBatis 操作接口

  操作接口(Mapper 接口)使用来帮助数据库和 POJO 映射的。

  注意: 仅仅为一个接口,不需要任何实现类。

  

package mybatis.dao;

 

  import mybatis.pojo.User;

  import org.springframework.stereotype.Repository;

   * @author enrace

  @Repository

  public interface MyBatisUserDao {

   * Get User.

   * @param id

   * @return User

   public User getUser(Long id);

  

 

  @Repository 用于标注数据访问组件,即 DAO 组件。

  除了 操作接口还需要创建映射文件,映射文件的 namespace 是与操作接口对应的。

  创建映射文件(小坑)和添加配置

  映射文件让 POJO (类) 能够与数据库的数据对应,是 xml 类型的。

  主要内容如下:

  

 ?xml version="1.0" encoding="UTF-8" ? 

 

   !DOCTYPE mapper

   PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"

   "http://mybatis.org/dtd/mybatis-3-mapper.dtd"

   mapper namespace="mybatis.dao.MyBatisUserDao"

   select id="getUser" parameterType="long" resultType="user"

   select id, user_name as userName, sex, note from t_user where id = #{id}

   /select

   /mapper

  

 

  主要的几个属性:

  namespace 指定一个接口,就是需要方法需要执行 sql 的接口。

   select 标签代表一个查询语句。

  id 指代这个 SQL,它与接口是同名的(个人认为是映射)。

  parameterType 是说明属性配置为 Long (个人理解为传入参数类型)。

  resultType 这里指定返回的类型(记得 @Alias 设置的别名就是 user ,那么到时会返回一个 User 实例)。

  然后再去 application.properties 添加如下信息:

  

# 数据库 url

 

  spring.datasource.url = jdbc:mysql://localhost:3306/xxx

  # 数据库用户名

  spring.datasource.username = zhangsan

  # 数据库密码

  spring.datasource.password = passwd123

  # 最大等待连接中的数量你,设置 0 没有限制

  spring.datasource.tomcat.max-idle = 10

  # 最大连接活动数

  spring.datasource.tomcat.max-active = 50

  # 最大等待毫秒数,单位 ms ,超过时间会出错误信息

  spring.datasource.tomcat.max-wait = 10000

  # 数据库连接池初始化连接数

  spring.datasource.tomcat.initial-size = 5

  # 映射文件配置

  mybatis.mapper-locations=classpath:mybatis/mapper/*.xml

  # 扫描别名包,和注解 @Alias 联用

  mybatis.type-aliases-package=mybatis.pojo

  # 配置 typeHandler 的扫描包

  mybatis.type-handlers-package=mybatis.typehandler

  #logging.level.root = DEBUG

  #logging.level.org.springframework = DEBUG

  #logging.level.org.org.mybatis = DEBUG

  

 

  小坑

  映射文件有了,我将它放在了项目 mybatis.mapper 包下,但是后面执行报了以下异常:

  

org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): mybatis.dao.MyBatisUserDao.getUser

 

  

 

  分析过程:

  classpath 指的文件目录是什么?

  classpath 指的是 build/resources (gradle 构建包) 或是 target/classes (maven 构建包)。

  结果:

  发现没有 mapper 目录和我的映射文件,手动添加可正常执行。

  解决方法一

  在 resources 资源目录创建 mybatis 目录和 mapper 子目录,将映射文件放入其中,原因是 resources 中的文件 gradle build 的时候会保留下来。这种是资源文件分离的方式。

  解决方法二

  build.gradle 中添加下面的代码:

  

sourceSets {

 

   main {

   resources {

   srcDirs src/main/java

  

 

  这是资源路径设置,添加代码后 gradle build 的时候不会删除 java 目录下的 非 .java 后缀文件。

  使用 MapperFactoryBean 装配 MyBatis 接口

  上面的 MyBatisUserDao 是一个 Mapper 接口,不可以使用 new 为其 生成对象实例。需要用到两个类,它 们 是 MapperFactoryBean 和 MapperScannerConfigurer 。其中 MapperFactoryBean 针对接口配置,MapperScannerConfigurer 则是扫描装配。书中提到 @MapperScan 可以后面去使用一下,它更为简便也是用来将对应接口扫描装配到 Spring IoC 容器中的。

  接下来我们创建一个 Bean 来配置 MyBatisUserDao 接口,在 @SpringBootApplication 注解文件下增加代码:

  

 @Autowired

 

   SqlSessionFactory sqlSessionFactory = null;

   * Define a Mapper interface of MyBatis.

   * @return MapperFactoryBean\ MyBatisUserDao\

   @Bean

   public MapperFactoryBean MyBatisUserDao initMyBatisUserDao() {

   MapperFactoryBean MyBatisUserDao bean = new MapperFactoryBean ();

   bean.setMapperInterface(MyBatisUserDao.class);

   bean.setSqlSessionFactory(sqlSessionFactory);

   return bean;

  

 

  SqlSessionFactory 是 Spring Boot 自动为我们生成的。

  开发服务层

  由于不是很难理解,直接上代码。

  服务接口类代码,如下:

  

package mybatis.service;

 

  import mybatis.pojo.User;

   * @author enrace

  public interface MyBatisUserService {

   * Get user object.

   * @param id

   * @return User

   public User getUser(Long id);

  

 

  实现类代码,如下:

  

package mybatis.service.impl;

 

  import mybatis.dao.MyBatisUserDao;

  import mybatis.pojo.User;

  import mybatis.service.MyBatisUserService;

  import org.springframework.beans.factory.annotation.Autowired;

  import org.springframework.stereotype.Service;

   * @author enrace

  @Service

  public class MyBatisUserServiceImpl implements MyBatisUserService {

   @Autowired

   private MyBatisUserDao myBatisUserDao = null;

   @Override

   public User getUser(Long id) {

   return myBatisUserDao.getUser(id);

  

 

  实现类中,通过 @Autowired 自动装配 MyBatisUserDao 的 Bean ,我们就实现了 getUser() 方法,从而可以获得 User 对象。

  创建控制器

  有了控制器就可以通过 url 测试结果。

  控制器代码,如下:

  

package mybatis.controller;

 

  import mybatis.pojo.User;

  import mybatis.service.MyBatisUserService;

  import org.springframework.beans.factory.annotation.Autowired;

  import org.springframework.web.bind.annotation.RequestMapping;

  import org.springframework.web.bind.annotation.RestController;

   * @author enrace

  @RestController

  public class MyBatisController {

   @Autowired

   private MyBatisUserService myBatisUserService = null;

   @RequestMapping("/getUser")

   public User getUser(Long id) {

   return myBatisUserService.getUser(id);

  

 

  @RequestMapping("/getUser") 设置请求的映射,通过传入 id 得到用户( JSON )格式。

  启动 Spring Boot 项目,访问 localhost:8080/getUser?id = 1

  至此,您已经了解到了 MyBatis 基本的执行过程,祝:事事无忧,天天无 BUG。

  以上就是MyBatis 初步(mybatis 教程)的详细内容,想要了解更多 MyBatis 初步的内容,请持续关注盛行IT软件开发工作室。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: