SSM之Mybatis

540 阅读7分钟

概述

Mybatis是一个持久层框架,它封装了JDBC操作的细节,使用了ORM思想实现了对结果集的封装
ORM:Object Relational Mappging(对象关系映射),就是把数据库表和实体类及实体类属性对应起来,使得我们操作实体类时就可以操作数据库表

使用步骤

下载jar包
创建mybatis-config.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">
创建数据库实体类和映射文件,配置配置头
<?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">
通过SqlSessionFactoryBuilder创建Factory
public class Demo1{
    public static void main(String[] args) {
        '加载mybatis的配置文件(映射)'
        InputStream in = Demo1.class.getClassLoader().getResourceAsStream("mybatis-config.xml");
        '构建sqlSession的工厂'
        SqlSessionFactory sf = new SqlSessionFactoryBuilder().build(in);
    }
}
mybatis-config配置文件解析
  • configuration主标签,所有的配置信息都要写在configuration中
  • properties标签:引入外部链接信息配置资源文件
  • settings标签:全局配置的属性
  • typeAliases标签:为实体类起别名,避免写过长的名字
<configuration>
    <!--引入jdbc.properties文件-->
    <properties resource="jdbc.properties"></properties>
    <settings>
        <!--打印日志信息-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
    <!-- 这个标签用来给实体类设置别名 -->
    <typeAliases>
    <!-- 通过遍历entity包下的实体类设置别名,别名是首字母小写,其他和类名一致 -->
        <package name="io.jtxyh.entity"/> 
    </typeAliases>
</configuration>

配置环境(按顺序配置)
  • environments标签
  • environment标签
  • transactionManager标签
  • dataSource标签:元素使用基本的JDBC数据源接口来配置JDBC连接对象的资源,有三种内建的数据源类型
  • UNPOOLED 每次创建新的连接
  • POOLED 创建连接池,用完归还
  • JNDI 获取JNDI连接池
  • property标签
  • mappers标签:sql映射语句一般定义在各持久类的Mapper.xml文件中,需要在配置中引用这些映射文件
<configuration>
<!-- default后的名字和environment的id保持一致 -->
<environments default="dev">  <!--默认运行环境ID-->
    <environment id="dev">    <!--运行环境ID,可以配置多个-->  
        <!-- 设置事务管理机制为JDBC -->
        <transactionManager type="JDBC"></transactionManager>
        <!-- 设置数据源:POOLED -->
        <!-- 使用mybatis内置的数据库连接池 -->
        <dataSource type="POOLED">
            <!-- 配置数据库连接 -->
            <property name="driver" value="com.mysql.jdbc.Driver" />
            <property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis" />
            <property name="username" value="root" />
            <property name="password" value="root" />
        </dataSource>
    </environment>

    <environment id="dev2"> 
        ....
    </environment>
</environments>
    <mappers>
        <mapper resource="io/jtxyh/dao/userInfo.xml"></mapper>
        <mapper resource="io/jtxyh/dao/userInfo-map.xml"></mapper>
    </mappers>
</configuration>

mybatis-mapper配置

  • mapper元素:后面的sql操作标签都必须配置在mapper标签中
  • select标签
  • id属性,类似方法名
  • parameterType属性,类似形参类型
  • resultType属性,类似返回值类型
  • insert标签,update标签,delete标签
  • id属性,类似方法名
  • 无返回值,没有returnType属性
  • insert标签对于自增id,可以用useGeneratedKeys="true" keyProperty="类的属性名"来获取新增记录id
  • sql标签:公共代码块,一般用来写数据库字段。在select中通过include标签引用sql标签id
  • resultMap标签:结果集映射,用来对实体类的属性与数据库的字段名做一一映射
  • type属性:写返回的结果集类型
  • id属性:定义一个id名字用于在select标签resultMap属性中调用
  • 写在resultMap标签内的标签:有通用属性property和column
  • id标签:用来确定数据库中的主键列
  • result标签:用来确定数据库中其他字段
  • association标签:持有关系查询(多对1,1对1)时使用
  • 在标签上写column=字段名,property=属性名,ofType=集合的泛型类型,select=二次查询的位置
  • 在标签上写column=字段名,property=属性名,ofType=集合的泛型类型,在标签内写id属性和result属性,通过sql语句进行多表查询
  • collection标签:聚合关系查询(多对多,1对多)时使用
  • 在标签上写column=字段名,property=属性名,javaType=属性的类型,select=二次查询的位置
  • 在标签上写column=字段名,property=属性名,javaType=属性的类型,在标签内写id属性和result属性,通过sql语句进行多表查询
<mapper namespace="io.jtxyh.dao.UserInfoDao">

    <resultMap type="Uinfo" id="selectUinfoAndCinfo">
        <id property="uid" column="uid" />
        <result property="uname" column="uname" />
        <result property="cid" column="cid" />

        <association property="cIf" column="cid" javaType="Cinfo"
            select="io.jtxyh.dao.CinfoDao.selectCinfoByCid">
        </association>

        <association property="cIf" column="cid" javaType="Cinfo">
            <id property="pid" column="pid" />
            <result property="pname" column="pname" />
        </association>

        --------------------------------------------------------------

        <collection property="minfoList" column="mid" ofType="Minfo" select="io.jtxyh.dao.MinfoDao.selectMinfoByMid">
        </collection>

        <collection property="minfoList" column="mid" ofType="Minfo">
            <id property="pid" column="pid" />
            <result property="pname" column="pname" />
        </collection>

    </resultMap>

    <sql id="mySql">cmid,cid,mid</sql>

    <!-- 第一个需要的参数使用的是mybatis已经设置好的别名 -->
    <!-- 第二个结果集对象写的是别名,因为在mybatis-config中配置了typeAliases标签,里面配置了别名
        全名应该是io.jtxyh.entity.UserInfo
    -->
    <!-- 实现模糊查询,使用百分号的时候必须加上双引号 -->
    <select id="getLikeUserInfo" parameterType="string" resultType="userInfo">
        select <include refid="mySql"/> 
        from userinfo 
        where upass like "%"#{upass}"%"
    </select>

    <insert id="addUserInfo">
        insert into uinfo values(#{uid},#{uname},#{cid})
    </insert>

    <delete id="deleteUserInfo">
        delete from uinfo where uid=#{uid}
    </delete>

    <update id="updateUserById" parameterType="Sysuser">
        update uinfo set uname=#{uname} where uid=#{uid}
    </update>

</mapper>

动态SQL

使用where,if实现条件查询:自动判断添加where和and

<select id="selectCondition" resultMap="selectCon">
    select cid,cname from cinfo
    <where>
        <!-- test中写条件 -->
        <if test="cid != null">
            and cid=#{cid}
        </if>
        <if test="cname != null">
            and cname=#{cname}
        </if>
    </where>
</select>
使用choose,when,otherwise实现判断选择单条件查询

<select id="selectOneCondition" resultMap="selectCon">
select cid,cname from cinfo
<where>
    <!-- 只要一个when匹配上就不判断后面的when, -->
    <!-- 全部没有匹配上就匹配otherwise里的 -->
    <choose>
        test中写条件
        <when test="cid != null">
            cid=#{cid}
        </when>
        <when test="cname != null">
            cname=#{cname}
        </when>
        <!-- 上述条件都不满足执行otherwise -->
        <otherwise>
            1=1
        </otherwise>
    </choose>
</where>
</select>

使用set,if实现条件更新:动态删除最后一个逗号

<update id="updateCondition">
    update cinfo
    <set>
        <if test="cname != null">
            cname=#{cname},
        </if>
        <if test="cpass != null">
            cpass=#{cpass},
        </if>
    </set>
    where cid=#{cid}
</update>

使用foreach批量添加/删除数据

  • collection属性:填list/array/自定义的属性的别名
  • item属性:填写自定义临时的循环变量的名字
  • separator属性:用什么来分割多个变量
  • open属性:以什么开始
  • close属性:以什么结束
  • index属性:遍历的索引
<!-- 批量添加数据 -->
<insert id="insertQuery">
    insert into cinfo (cid,cname) values
    <foreach collection="cin" item="c" separator=",">
        (#{c.cid},#{c.cname})
    </foreach>
</insert>
<!-- 批量删除数据 -->
<delete id="deleteQuery">
    delete from cinfo where cid in
    <foreach collection="cidList" item="cid" open="(" close=")"
        separator=",">
        #{cid}
    </foreach>
</delete>

延迟加载

当数据量比较大的时候,预先仅加载一部分数据返回用户,加快操作响应速度
<!-- 在mybatis-config.xml中配置这些 -->
<settings>
    <setting name="logImpl" value="STDOUT_LOGGING"/>
        <!-- 启用延迟加载 -->
        <setting name="lazyLoadingEnabled" value="true"/>
        <!-- 积极加载改为消极加载 -->
        <setting name="aggressiveLazyLoading" value="false"/>
        <!-- 调用toString,equals不触发延迟对象的加载 -->
        <setting name="lazyLoadTriggerMethods" value=""/>
</settings>

缓存

一级缓存:一级缓存是默认开启的,缓存存在于session中,每次关闭session或者使用增删改时清理缓存
二级缓存:使用查询时,查询结果会存入对应的namespace中,使用增删改时清理缓存
<!-- 在mybatis-config.xml中配置 -->
<settings>
    <!-- 启用二级缓存 -->
    <setting name="cacheEnabled" value="true"/>
</settings>

<!-- 在mybatis-mapper.xml中配置 -->
<mapper namespace="io.jtxyh.dao.CinfoDao">
    <!-- 
        配置缓存策略
        eviction=FIFO代表缓存方式为先进先出
        flushInterval=60000代表60秒中刷新一次缓存,
        size=512代表缓存为512个字节
        readOnly=true代表缓存为只读
     -->
    <cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"></cache>
</mapper>

往期推荐