2. MyBatis - 深度学习 - 基本使用

前言

本文整理一下MyBatis的基本使用,这里非工作中使用的场景,主要为了分析源码而做准备

预备数据库

如果你使用docker的话,推荐看看我的文章把 [Docker 实战系列 - MySQL环境](…/…/Docker/实战系列/Docker 实战系列 - MySQL环境.md)

创建数据库

# 创建库
create database mybatis_demo;

创建表

CREATE TABLE `student` (
  `id` int(10) NOT NULL AUTO_INCREMENT,
  `cls_id` int(10) NOT NULL COMMENT '班级ID',
  `name` varchar(32) NOT NULL COMMENT '名字',
  `age` int(3) NOT NULL COMMENT '年龄',
  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;
CREATE TABLE `cls` (
  `id` int(10) NOT NULL AUTO_INCREMENT,
  `name` varchar(32) NOT NULL COMMENT '班级名称',
  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;

插入测试数据

INSERT INTO `student`(`id`, `cls_id`, `name`, `age`, `create_time`) VALUES (1, 1, '张三', 13, now());
INSERT INTO `student`(`id`, `cls_id`, `name`, `age`, `create_time`) VALUES (2, 2, '李四', 14, now());
INSERT INTO `cls`(`id`, `name`, `create_time`) VALUES (1, '初一1班', now());
INSERT INTO `cls`(`id`, `name`, `create_time`) VALUES (2, '初一2班', now());

创建项目

在上文中已经创建好了mybatis的源码环境,现在我们开始创建自己的项目

在这里插入图片描述
设置自己的包名,我为了以后复习所以用了 chapter1

在这里插入图片描述

准备工作

配置properties文件

vim application.properties
jdbc.driver=com.mysql.jdbc.Driver
default.environment=dev

全局配置

vim mybatis-config.xml

属性配置优先级

  • build方式
  • 外部的 properties 文件
  • xml配置的properties
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- 这里只是演示,正常你使用 app.properties 配置即可 -->
    <properties resource="application.properties">
        <property name="jdbc.driver" value="com.mysql.jdbc.Driver"/>
    </properties>
    <!-- 如果需要远程加载的话可以使用url 只能选一种-->
    <!-- <properties url=""> -->

    <environments default="${default.environment}">
        <!-- 测试环境 -->
        <environment id="dev">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="jdbc:mysql://localhost/mybatis_demo"/>
                <property name="username" value="root"/>
                <property name="password" value="a123456"/>
            </dataSource>
        </environment>
        <!-- 生产环境 -->
        <environment id="pro">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="jdbc:mysql://192.168.160.130/mybatis_online"/>
                <property name="username" value="root"/>
                <property name="password" value="Aa123456"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
  		...
    </mappers>
</configuration>

定义 Student 并使用 lombok [Lombok 的使用](…/…/Java/编程技巧/Lombok 的使用.md)

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {
    private Integer id;
    private Integer clsId;
    private String name;
    private Date createTime;
}

现在项目结构

├── pom.xml
└── src
    ├── main
    │   ├── java
    │   │   └── com
    │   │       └── xm
    │   │           └── chapter1
    │   │               ├── MainTest.java
    │   │               ├── Student.java
    │   │               └── StudentMapper.xml
    │   └── resources
    │       ├── application.properties
    │       └── mybatis-config.xml
    └── test
        └── java

XML方式

自定义Mapper.xml

vim StudentMapper.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="com.xm.chapter1.StudentMapper">
    <select id="selectStudentXml" resultType="com.xm.chapter1.Student" >
        select * from student where id = #{id}
     </select>
</mapper>

修改全局配置的mapper,并引入我们的文件

vim mybatis-config.xml
<configuration>
  ...
    <mappers>
        <mapper resource="com/xm/chapter1/StudentMapper.xml"/>
    </mappers>
</configuration>

运行

public class MainTest {
    private SqlSession session;

    @Before
    public void init() throws IOException {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        session = sqlSessionFactory.openSession(true);
    }

    @Test
    public void test1() throws IOException {
        // 通过xml查询
        Student result = session.selectOne(
          "com.xm.chapter1.StudentMapper.selectStudentXml", 1);
        System.out.println(result.toString());
    }
}

对于结果的转移,不知道你有没有发现两个字段(createTime,clsId)为空,我们来修改一下

<?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="com.xm.chapter1.StudentMapper">

    <resultMap id="StudentMap" type="com.xm.chapter1.Student">
        <id property="id" column="id"/>
        <result property="clsId" column="cls_id"/>
        <result property="createTime" column="create_time"/>
    </resultMap>

    <select id="selectStudentXml" resultMap="StudentMap" >
        select * from student where id = #{id}
     </select>

</mapper>

接口方式

为了避免混淆,可以先把上面的xml删除,或者不删除屏蔽掉下面的即可

修改全局配置,引入接口方式

<configuration>
    ...
    <mappers>
        <mapper class="com.xm.chapter1.StudentMapper"/>
    </mappers>
</configuration>

创建mapper接口

public interface StudentMapper {
    @Select("select * from student where id = #{id}")
    Student selectInterface(Integer id);
}

运行

public class MainTest {
		....
    @Test
    public void test2(){
        StudentMapper mapper = session.getMapper(StudentMapper.class);
        Student student = mapper.selectInterface(1);
        System.out.println(student);
    }
}

对于结果的转移,不知道你有没有发现两个字段(createTime,clsId)为空,我们来修改一下

public interface StudentMapper {

  @Select("select id,name,cls_id as clsId,create_time as createTime from student where id = #{id}")
  Student selectInterface(Integer id);
}

类型处理器

持久层框架其中比较重要的工作就是处理数据的映射转换,把java 类型转换成jdbc 类型的参数,又需要把jdbc 类型的结果集转换成java 类型。

public interface TypeHandler<T> {
  void setParameter(
    PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException;
  T getResult(ResultSet rs, String columnName) throws SQLException;
  T getResult(ResultSet rs, int columnIndex) throws SQLException;
  T getResult(CallableStatement cs, int columnIndex) throws SQLException;
}

我们将上面的student的事件类型,修改为long试下

...
  public class Student {
    private Integer id;
    private String name;
    private Integer clsId;
    // 改这里
    private Long createTime;
}

运行后发现结果不符合我们预期

Student(id=1, name=张三, clsId=1, createTime=2019)

自定义TypeHandler解决这个问题

public class LongTimeHandler extends BaseTypeHandler<Long> {
  @Override
  public void setNonNullParameter(
    PreparedStatement ps, int i, Long parameter, JdbcType jdbcType) throws SQLException {
    ps.setDate(i, new Date(parameter));
  }

  @Override
  public Long getNullableResult(ResultSet rs, String columnName) throws SQLException {
    return rs.getDate(columnName).getTime();
  }

  @Override
  public Long getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
    return rs.getDate(columnIndex).getTime();
  }

  @Override
  public Long getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
    return cs.getDate(columnIndex).getTime();
  }
}

全局配置的方式 - 任选一

<configuration>
  <typeHandlers>
    <typeHandler handler="com.xm.chapter1.LongTimeHandler"
                 javaType="long" jdbcType="TIMESTAMP" />
  </typeHandlers>
</configuration>
// 如果嫌弃上面写 javaType、jdbcType 麻烦,可以使用注解
@MappedJdbcTypes(JdbcType.TIMESTAMP)
@MappedTypes(Long.class)
public class LongTimeHandler extends BaseTypeHandler<Long> {
	....
}

针对单个返回值 - 任选一

<mapper namespace="com.xm.chapter1.StudentMapper">
  <resultMap id="StudentMap" type="com.xm.chapter1.Student">
     ...
      <result property="createTime" 
              column="create_time" typeHandler="com.xm.chapter1.LongTimeHandler"/>
  </resultMap>
	....
</mapper>

返回结果

Student(id=1, name=张三, clsId=1, createTime=1562342400000)

日志

创建文件

vim resources/log4j.properties

log4j.properties

### 设置日志级别 ###
log4j.rootLogger = debug,stdout
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern =  %d{ABSOLUTE} %5p %c:%L - %m%n
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章