MyBatis 第三十章 MyBatis 核心配置文件深入


MyBatis —— 第三十章 MyBatis 核心配置文件深入


1. typeHandlers 标签

无论是 MyBatis 在预处理语句(PreparedStatement)中设置一个参数时,还是从结果集中取出一个值时,都会用类处理器将获取的值以合适的方式转换成 Java 类型。下表描述了一些默认的类型处理器(部分)。

类型处理器 Java 类型 JDBC 类型
BooleanTypeHandler java.lang.Boolean,boolean 数据库兼容的 BOOLEAN
ByteTypeHandler java.lang.Byte,byte 数据库兼容的 NUMERIC 或 BYTE
ShortTypeHandler java.lang.Short,short 数据库兼容的 NUMERIC 或 SHORT INTEGER
IntegerTypeHandler java.lang.Integer,int 数据库兼容的 NUMERIC 或 INTEGER
LongTypeHandler java.lang.Long,long 数据库兼容的 NUMERIC 或 LONG INTEGER

你可以重写类型处理器或创建自己的类型处理器来处理不支持的或非标准的类型,具体做法为:实现 org.apache.ibatis.type.TypeHandler 接口,或者继承一个相当方便的类 org.apache.ibatis.type.BaseTypeHandler,然后可以选择性地将它映射到一个 JDBC 类型。例如:一个 Java 中的 Date 类型,要想将之存到数据库的时候储存为一个 1970 至今的毫秒数(Timestamp),取出来时转换成 Java 的 Date,即 Java 中的 Date 与数据库中的 varchar 毫秒值之间的转换。

开发步骤:

  1. 定义转换继承类 BaseTypeHandler<T>
  2. 覆盖 4 个未实现的方法,其中 setNonNullParameter 为 Java 程序设置数据到数据库的回调方法,getNullableResult 为查询时 MySQL 的字符串类型转换成 Java 的 Type 类型的方法
  3. 在 MyBatis 核心配置文件中进行注册
  4. 测试转换是否正确

示例代码:

sqlMapConfig.xml

<?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>
    <!-- Load the external properties file through the properties tag -->
    <properties resource="jdbc.properties"></properties>
    <!-- Define alias -->
    <typeAliases>
        <typeAlias type="com.gregperlinli.domain.User" alias="user" />
    </typeAliases>
    <!-- Custom type handler -->
    <typeHandlers>
        <typeHandler handler="com.gregperlinli.handler.DateTypeHandler" />
    </typeHandlers>
    <!-- Data source environment -->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="POOLED">
                <property name="driver" value="$&#123;jdbc.driver&#125;"/>
                <property name="url" value="$&#123;jdbc.url&#125;"/>
                <property name="username" value="$&#123;jdbc.username&#125;"/>
                <property name="password" value="$&#123;jdbc.password&#125;"/>
            </dataSource>
        </environment>
    </environments>
    <!-- Load mapping profile -->
    <mappers>
        <mapper resource="com/gregperlinli/mapper/UserMapper.xml"></mapper>
    </mappers>
</configuration>

com/yourname/mapper/userMapper.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.gregperlinli.mapper.UserMapper">
    <insert id="save" parameterType="user">
        insert into user values(#&#123;id&#125;, #&#123;username&#125;, #&#123;password&#125;, #&#123;birthday&#125;)
    </insert>
    <select id="findById" parameterType="int" resultType="user">
        select  * from user where id = #&#123;id&#125;
    </select>
</mapper>

com.yourname.domain.User

/**
 * @author gregPerlinLi
 * @since 2021-10-08
 */
public class User &#123;
    private int id;
    private String username;
    private String password;
    private Date birthday;

    public int getId() &#123;
        return id;
    &#125;
    public void setId(int id) &#123;
        this.id = id;
    &#125;
    public String getUsername() &#123;
        return username;
    &#125;
    public void setUsername(String username) &#123;
        this.username = username;
    &#125;
    public String getPassword() &#123;
        return password;
    &#125;
    public void setPassword(String password) &#123;
        this.password = password;
    &#125;
    public Date getBirthday() &#123;
        return birthday;
    &#125;
    public void setBirthday(Date birthday) &#123;
        this.birthday = birthday;
    &#125;
    @Override
    public String toString() &#123;
        return "User&#123;" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '&#125;';
    &#125;
&#125;

com.yourname.mapper.UserMapper

/**
 * @author gregPerlinLi
 * @since 2021-10-08
 */
public interface UserMapper &#123;
    /**
     * save user
     *
     * @param user user to save
     */
    void save(User user);
    /**
     * Find by id
     *
     * @param id id to find
     * @return user
     */
    User findById(int id);
&#125;

com.yourname.handler.DateTypeHandler

/**
 * @author gregPerlinLi
 * @since 2021-10-12
 */
public class DateTypeHandler extends BaseTypeHandler<Date> &#123;
    /**
     * Convert Java types to the types required by the database
     */
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Date parameter, JdbcType jdbcType) throws SQLException &#123;
        long time = parameter.getTime();
        ps.setLong(i, time);
    &#125;
    /**
     * Convert types in the database to Java types
     * @param columnName Field names to convert
     * @param rs Queried result set
     */
    @Override
    public Date getNullableResult(ResultSet rs, String columnName) throws SQLException &#123;
        // Obtain the data (Long) required in the result set, convert it into Date type and return it
        long aLong = rs.getLong(columnName);
        Date date = new Date(aLong);
        return date;
    &#125;
    /**
     * Convert types in the database to Java types
     */
    @Override
    public Date getNullableResult(ResultSet rs, int columnIndex) throws SQLException &#123;
        long aLong = rs.getLong(columnIndex);
        Date date = new Date(aLong);
        return date;
    &#125;
    /**
     * Convert types in the database to Java types
     */
    @Override
    public Date getNullableResult(CallableStatement cs, int columnIndex) throws SQLException &#123;
        long aLong = cs.getLong(columnIndex);
        Date date = new Date(aLong);
        return date;
    &#125;
&#125;

com.yourname.test.MybatisTest

/**
 * @author gregPerlinLi
 * @since 2021-10-08
 */
public class MybatisTest &#123;
    @Test
    public void test1() throws IOException &#123;
        InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        // Create user
        User user = new User();
        user.setUsername("Test");
        user.setPassword("abc");
        user.setBirthday(new Date());
        // Perform save operation
        userMapper.save(user);
        sqlSession.commit();
        sqlSession.close();
    &#125;
    @Test
    public void test2() throws IOException &#123;
        InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user = userMapper.findById(8);
        System.out.println("The birthday of the user is: " + user.getBirthday());
        sqlSession.commit();
        sqlSession.close();
    &#125;
&#125;

2. plugins 标签

MyBatis 可以使用第三方的插件来对功能进行拓展。其中,分页助手 PageHelper 是将分页的复杂操作进行封装,使用简单的方式即可获得分页的相关数据

开发步骤:

  1. 导入通用 PageHelper 的坐标

    <dependency>
        <groupId>com.github.pagehelper</groupId>
        <artifactId>pagehelper</artifactId>
        <version>3.7.5</version>
    </dependency>
    <dependency>
        <groupId>com.github.jsqlparser</groupId>
        <artifactId>jsqlparser</artifactId>
        <version>0.9.1</version>
    </dependency>
    
  2. 在 MyBatis 核心配置文件中配置 PageHelper 插件

    <!-- Configure plugins -->
    <plugins>
        <plugin interceptor="com.github.pagehelper.PageHelper">
            <property name="dialect" value="mysql"/>
        </plugin>
    </plugins>
    
  3. 测试分页数据获取

示例代码:

pom.xml

<dependencies>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>4.0.1</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-api</artifactId>
        <version>$&#123;junit.version&#125;</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-engine</artifactId>
        <version>$&#123;junit.version&#125;</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.25</version>
    </dependency>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.7</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.13.2</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>
    <dependency>
        <groupId>com.github.pagehelper</groupId>
        <artifactId>pagehelper</artifactId>
        <version>3.7.5</version>
    </dependency>
    <dependency>
        <groupId>com.github.jsqlparser</groupId>
        <artifactId>jsqlparser</artifactId>
        <version>0.9.1</version>
    </dependency>
</dependencies>

sqlMapConfig.xml

<?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>
    <!-- Load the external properties file through the properties tag -->
    <properties resource="jdbc.properties"></properties>
    <!-- Define alias -->
    <typeAliases>
        <typeAlias type="com.gregperlinli.domain.User" alias="user" />
    </typeAliases>
    <!-- Configure plugins -->
    <plugins>
        <plugin interceptor="com.github.pagehelper.PageHelper">
            <property name="dialect" value="mysql"/>
        </plugin>
    </plugins>
    <!-- Data source environment -->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="POOLED">
                <property name="driver" value="$&#123;jdbc.driver&#125;"/>
                <property name="url" value="$&#123;jdbc.url&#125;"/>
                <property name="username" value="$&#123;jdbc.username&#125;"/>
                <property name="password" value="$&#123;jdbc.password&#125;"/>
            </dataSource>
        </environment>
    </environments>
    <!-- Load mapping profile -->
    <mappers>
        <mapper resource="com/gregperlinli/mapper/UserMapper.xml"></mapper>
    </mappers>
</configuration>

com/yourname/mapper/UserMapper.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.gregperlinli.mapper.UserMapper">
    <select id="findAll" resultType="user">
        select * from user
    </select>
</mapper>

com.yourname.mapper.UserMapper

/**
 * @author gregPerlinLi
 * @since 2021-10-08
 */
public interface UserMapper &#123;
    /**
     * Find all
     * @return All users
     */
    List<User> findAll();
&#125;

com.yourname.test.MybatisTest


/**
 * @author gregPerlinLi
 * @since 2021-10-08
 */
public class MybatisTest &#123;
    @Test
    public void test() throws IOException &#123;
        InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        // Set paging related parameters    Current page + Number of displays per page
        PageHelper.startPage(1, 3);
        List<User> userList = userMapper.findAll();
        userList.forEach(System.out::println);
        // Get paging related parameters
        PageInfo<User> userPageInfo = new PageInfo<>(userList);
        System.out.println("|Current page: " + userPageInfo.getPageNum() +
                            "|\t|Number of displays per page: " + userPageInfo.getPageSize() +
                            "|\t|Total number: " + userPageInfo.getTotal() +
                            "|\t|Total pages: " + userPageInfo.getPages() +
                            "|\t|Previous page:" + userPageInfo.getPrePage() +
                            "|\t|Next page:" + userPageInfo.getNextPage() +
                            "|\t|Is the first page: " + userPageInfo.isIsFirstPage() +
                            "|\t|Is the last page: " + userPageInfo.isIsLastPage() + "|");
        sqlSession.close();
    &#125;
&#125;

3. 知识要点

MyBatis 核心文件配置常用标签:

  1. <properties>:该标签可以加载外部的 properties 文件
  2. <typeAliases>:设置类型别名
  3. <environments>:数据源环境配置标签
  4. <typeHandlers>:配置自定义类型处理器
  5. <plugins>:配置 MyBatis 插件


文章作者: gregPerlinLi
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 gregPerlinLi !
  目录