跳转至

MyBatis框架支持

MyBatis框架支持

本文档描述了 SeaboxSQL 数据库对于MyBatis框架的支持情况和配置说明,面向所有使用SeaboxSQL数据库的用户,主要是数据库管理员和应用程序开发人员。

有关 MyBatis 的更多信息,请参阅以下资源:

MyBatis 中文网https://mybatis.net.cn/

概述

MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Old Java Objects, 普通的Java对象) 映射成数据库中的记录。

在本章中详细说明了SeaboxSQL对MyBatis 的支持情况,以及使用时应该注意的问题。

本章内容主要是基于MyBatis3及后续版本支持情况的详细描述

MyBatis 配置说明

Mybatis的jar包可以从官方网站下载,Mybatis所使用的SeaboxSQL JDBC驱动包seaboxsql-jdbc-xxx.jar可以从公司获取,使用时将Mybatis包和 JDBC包导入到项目的Libraries中并定义相关配置项即可。

Mybatis使用原理图

在 config.xml 中配置 JDBC 的驱动信息参数,数据库服务器信息参数和登陆用户信息参数。当然,这些参数也可以根据用户应用需求,单独生成 property 文件,针对不用的应用场景,导入不同的属性文件。这里以property为例说明下 config.xml 的配置使用。

property jdbc文件内容举例:

说明:jdbc:seaboxsql://ip1:7300,ip2:7301/库名?targetServerType=any&loadBalanceHosts=true为SeaboxSQL连接高可用写法,该用户为sql任务轮询访问数据库不同的管理接口达到任务数量上的负载均衡。支持其中一个ip失效后只访问另一个ip,达到高可用的目的。

jdbc.driverClassName=com.seaboxsql.Driver
jdbc.url=jdbc:seaboxsql://ip1:7300,ip2:7301/库名?targetServerType=any&loadBalanceHosts=true
jdbc.username=mppadmin
jdbc.password=mppadmin

在 config.xml 中增加如下声明:

<environments default="development">
	<environment id="development">
		<transactionManager type="JDBC"/>
		<dataSource type="POOLED">
			<property name="driver" value="${jdbc.driverClassName}"/>
			<property name="url" value="${jdbc.url}"/>
            <property name="username" value="${jdbc.username}" />
            <property name="password" value="${jdbc.password}" />
		</dataSource>
	</environment>
</environments>

在 mapper.xml中,主要是配置 SQL 映射关系,根据用户的需求,自定义映射关系。这里以一个简单的配置为例。在mapper.xml 中增加如下声明:

<mapper namespace="com.test.interfaces.MybatisDao">
	<update id="dropTable">
		DROP TABLE IF EXISTS ${sql} CASCADE
	</update>
	<update id="createNewTableMap" parameterType="java.util.HashMap">
		${sql}
	</update>
    <resultMap id="NumTableMap" type="NumEntity">
        <result column="id" property="userId" />
        <result column="age" property="userAge" />
        <result column="name" property="userName" />
        <result column="wage" property="userWage" />
        <result column="cost" property="userCost" />
    </resultMap>
    <select id="selectNumTable" resultMap="NumTableMap">
        select * from t_num
    </select>
    <select id="selectNumTableByID" parameterType="int" resultMap="NumTableMap">
        select * from t_num where id=#{value}
    </select>
    <select id="selectNumTableByAge" parameterType="int" resultMap="NumTableMap">
        select * from t_num where age=#{value}
    </select>
    <select id="selectNumTableByName" parameterType="string" resultMap="NumTableMap">
        select * from t_num where name=#{value}
    </select>
    <insert id="insertNumTable" parameterType="NumEntity" keyProperty="userId">
        insert into t_num(id,age,name,wage,cost)
        values(#{userId},#{userAge},#{userName},#{userWage},#{userCost})
    </insert>
    <update id="updateNumTableById" parameterType="NumEntity" >
        update t_num set age=#{userAge},name=#{userName},wage=#{userWage},cost=#				{userCost}where id=#{userId}
    </update>
    <delete id="deleteNumTableById" parameterType="int">
    	delete from t_num where id=#{value}
    </delete>
    <delete id="deleteNumTable">
    	delete from t_num
    </delete>
</mapper>

至此,MyBatis 的属性文件和映射文件的配置工作已经完成,接下来是来完成 Java 中对应的接口和实例的开发工作。

MyBatis 程序示例

接口和实例开发示例
  • 在 Java 中读取 property 和 config 属性,配置到 sqlSessionFactory:
@BeforeClass
public static void setUpClass() throws Exception {
    InputStream fis = null;
    InputStream inputStream = null;
    try {
        /* 创建一个 sqlSessionFactory */
        Properties prop = new Properties();
        fis = Resources.getResourceAsStream("propertty");
        prop.load(fis);
        inputStream = Resources.getResourceAsStream("MyConfig.xml");
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream,
        "development", prop);
    } catch(Exception e) {
    e.printStackTrace();
    }
}
  • 在 Java 中配置 mapper.xml 对应的 namespace,为 Interface 类型:
public interface MybatisDao {
    int createNewTableMap(Map<String, Object> param);
    int dropTable(Map<String, Object> param);
    public List<NumEntity> selectNumTable();
    public NumEntity selectNumTableByID(int id);
    public List<NumEntity> selectNumTableByAge(int age);
    public List<NumEntity> selectNumTableByName(String name);
    public void insertNumTable(NumEntity user);
    public void updateNumTableById(NumEntity user);
    public void deleteNumTableById(int id);
    public void deleteNumTable();
}
  • 在 Java 中进行表的查询操作:
public void testNumTable() {
    SqlSession session = sqlSessionFactory.openSession();
    int i = 1;
    try {
        MybatisDao userOperation = session.getMapper(MybatisDao.class);
        List<NumEntity> users = userOperation.selectNumTable();
        for (NumEntity user : users) {
            System.out.println(user);
            Assert.assertEquals(i, user.getId());
            Assert.assertEquals(AGE+i, user.getUserAge());
            Assert.assertEquals(name[i], user.getUserName());
            Assert.assertEquals("yes",WAGE+(double)(i*100)/(double)(3.0),
            user.getUserWage(),0.000001);
            Assert.assertEquals("yes",COST+(double)(i*100)/(double)(3.0),
            user.getUserCost(),0.01);
            i++;
    	}
    } finally {
    session.close();
    }
}
  • 在 Java 中进行表的插入操作:
public void testInsertNumTable() {
    int i = 1 ;
    SqlSession session = sqlSessionFactory.openSession();
    try {
        MybatisDao userOperation = session.getMapper(MybatisDao.class);
        NumEntity user = new NumEntity();
        name[1] = " 张三";
        name[2] = " 李四";
        name[3] = " 王五";
        name[4] = " 赵二";
        name[5] = " 小北";
        name[6] = " 小东";
        name[7] = " 小西";
        name[8] = " 小南";
        name[9] = " 小明";
        for (i=1;i<10;i++) {
            user.setId(i);
            user.setUserAge(AGE+i);
            user.setUserName(name[i]);
            user.setUserWage(WAGE+(double)(i*100)/(double)(3.0));
            user.setUserCost(COST+(double)(i*100)/(double)(3.0));
            userOperation.insertNumTable(user);
            session.commit();
            System.out.println(user);
    }
    } finally {
    session.close();
    }
}
  • 在 Java 中进行表的更新操作:
public void testUpdateNumTable() {
    int i = 1 ;
    SqlSession session = sqlSessionFactory.openSession();
    try {
        MybatisDao userOperation = session.getMapper(MybatisDao.class);
        NumEntity user = new NumEntity();
        /* 更新一行新的数据 id=1 */
        user = userOperation.selectNumTableByID(1);
        user.setUserAge(AGE+i);
        user.setUserName(name[0]);
        user.setUserWage(WAGE+(double)(i*100)/(double)(3.0));
        user.setUserCost(COST+(double)(i*100)/(double)(3.0));
        userOperation.updateNumTableById(user);
        session.commit();
    } finally {
    session.close();
    }
}
  • 在 Java 中进行表的删除操作:
public void testDeleteNumTable() {
    int i = 1 ;
    SqlSession session = sqlSessionFactory.openSession();
    try {
        MybatisDao userOperation = session.getMapper(MybatisDao.class);
        userOperation.deleteNumTable();
        session.commit();
    } finally {
    session.close();
    }
}
存储过程的使用

如果开发过程中需使用数据库的存储过程,可在 mapper.xml 中增加如下内容:

<select id="getPerson" resultType="java.util.Map" statementType="CALLABLE">
    {
    call getPerson(
    #{a,mode=IN,jdbcType=INTEGER},
    #{b,mode=OUT,jdbcType=VARCHAR},
    #{param2,mode=OUT,javaType=ResultSet,jdbcType=OTHER,resultMap=cursorMap}
    )
    }
</select>

创建表和数据:

create or replace function getPerson(b out refcursor)
as $$
begin
open b for select * from person;
end;
$$ language plpgsql;

调用存储过程:

Map<String, Object> map = mapper.getPerson2(null, null, null);
ResultSet o = (ResultSet) map.get("getperson2");
o.next();
System.out.println(o.getString(1));
System.out.println(o.getString(2));
System.out.println(o.getString(3));

MyBatis 注意点

  • SeaboxSQL 支持array数据类型,在MyBatis中需要增加ArrayTypeHandler来处理这一特殊类型;

  • SeaboxSQL 支持json数据类型,在Mybatis中需要增加JsonTypeHandler来处理这一特殊类型;

  • SeaboxSQL 支持hstore数据类型,在Mybatis中需要增加HstoreTypeHandler来处理这一特殊类型;

  • SeaboxSQL 支持XML数据类型,在Mybatis的映射中,需要对xml数据类型做标注,如:

insert into t_xml(value) values ((#{content})::xml)
  • SeaboxSQL 适配 Mybatis 的 pagehelper插件时,由于无法通过连接自动获取数据库类型,需要将 helperDialect设置成postgresql,配置如下:
<plugins>
    <!-- com.github.pagehelper 为 PageHelper 类所在包名 -->
    <plugin interceptor="com.github.pagehelper.PageInterceptor">
        <property name="helperDialect" value="postgresql" />
    </plugin>
</plugins>