导航

mybatis学习笔记

Posted on 2019-04-18 13:27  李日天  阅读(167)  评论(0编辑  收藏  举报

mybatis体系结构

 

 

开发步骤

配置文件

mybatis.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>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/java?"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>

<mappers>
<mapper resource="org/mybatis/example/BlogMapper.xml"/>
</mappers>
</configuration>

mapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="xxx">
    <insert id="insertTeacher" parameterType="com.mybatisLearn.beans.Teacher">
    insert into teacher(name,age,lesson) values (#{name},#{age},#{lesson})
   </insert>
</mapper>

它根据传进来的类的属性来找值,属性是指实现了get set方法的。

一个简单的Teacher实体类,该类用来定义表的结构,对于必要的属性,必须实现get set方法。

package com.mybatisLearn.beans;

public class Teacher {
    private String name;
    private Integer age;
    private String lesson;
  //记得实现一个无参方法,不然mybatis只会调用有参构造器,从而报错。
  public Teacher(){}
public Teacher(String name, Integer age, String lesson) {
        this.name = name;
        this.age = age;
        this.lesson = lesson;
    }
    @Override
    public String toString() {
        return "Teacher{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", lesson='" + lesson + '\'' +
                '}';
    }
    public String getName() {return name;}
    public void setName(String name) {this.name = name;}
    public Integer getAge() {return age;}
    public void setAge(Integer age) {this.age = age;}
    public String getLesson() {return lesson;}
    public void setLesson(String lesson) {this.lesson = lesson;}
}

Dao层的实现

package com.mybatisLearn.dao;

import com.mybatisLearn.beans.Teacher;

import java.io.IOException;
import java.io.InputStream;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

public class ITeacherDaoImpl implements ITeacherDao {
@Override
public void insert(Teacher teacher) {
SqlSession sqlSession = null;
try {
// 加载主配置文件
InputStream inputStream = Resources.getResourceAsStream("mybatis.xml");
// 创建sqlsessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 创建sqlSession
sqlSession = sqlSessionFactory.openSession();
// 操作
sqlSession.insert("insertTeacher", teacher);
// 提交操作
sqlSession.commit();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (sqlSession != null) {
sqlSession.close();
}
}
}
}

 

测试一下

package com.mybatisLearn.Test;

import com.mybatisLearn.beans.Teacher;
import com.mybatisLearn.dao.ITeacherDao;
import com.mybatisLearn.dao.ITeacherDaoImpl;
import org.junit.Before;
import org.junit.Test;

public class ATest {
    private ITeacherDao dao;
    @Before
    public void before(){
        dao = new ITeacherDaoImpl();
    }
    
    @Test
    public void test(){
        Teacher teacher = new Teacher("李花",22,"人工智能");
        dao.insert(teacher);
    }
}

 

Done!

 

Mapper中namespace

当多个mapper文件中有重名的sql时,会报错

Error updating database.  Cause: java.lang.IllegalArgumentException: insertTeacher is ambiguous in Mapped Statements collection (try using the full name including the namespace, or rename one of the entries)

需要指明使用

sqlSession.insert("test01.insertTeacher", teacher);

 

从属性文件中读取jdbc连接要素

jdbc_mysql.properties

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/java?serverTimezone=GMT%2B8
jdbc.username=root
jdbc.password=baobao521

mybatis.xml

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

 

 

别名

mapper.xml 中每条语句都要写parameterType太冗余,可以使用别名

在mybatis.xml中配置

    <typeAliases>
        <typeAlias type="com.mybatisLearn.beans.Teacher" alias="Teacher"/>
    </typeAliases>

mapper.xml中可以简写

    <insert id="insertTeacher" parameterType="Teacher">
        insert into teacher(name,age,lesson) values (#{name},#{age},#{lesson})
    </insert>

 

但是每个表都要写的话还是很冗余,使用package可以更简单,可以将包中的简单类名当作别名。

    <typeAliases>
        <package name="com.mybatisLearn.beans"/>
    </typeAliases>

 

使用别名解决字段不一致问题

有时候,实体类的字段名和属性名可能不一致,这时可以通过别名来解决

    <select id="xx" resultType="Teacher">
        select tid id, tname name, tage age from teacher 
    </select>

 

使用resultmap来解决不一致问题

    <resultMap id="studentMapper" type="Student">
        <id column="id" property="id"></id>
        <result column="sname" property="age"></result>
        <result column="sname" property="name"></result>
    </resultMap>

 

实现mapper的动态代理

// 通过sqlSession中的getMapper方法来动态加载Dao类, 
sqlSession = MyBatisUtils.getSqlSession(); studentdao = sqlSession.getMapper(IStudentDao.class);
// 保证命名一致, 只需调用mapper中注册方法的id就可以
List<Student> students = studentdao.queryAll();

 

使用Map实现多条件查询

Map<String, Object> map = new HashMap<String, Object>();
map.put("name", "李");
map.put("age",15);
List<Student> students = studentdao.queryMuti(map);
<select id="queryMuti" resultType="Student">
    select name,age,id from student where name like '%' #{name} '%' and age > #{age}
</select>

 

使用索引号实现多条件查询

List<Student> students = studentdao.queryMuti2("李", 15);

 

<select id="queryMuti2" resultType="Student">
select name,age,id from student where name like '%' #{arg0} '%' and age > #{arg1}
</select>

 

 

动态SQL

<mapper namespace="com.DymicSqlLearn.Dao.IUserDao">
<select id="selectStudentByCondition" resultType="User">
select id, username, password, role
from user
<where>
<if test="arg0 != null and arg0 != ''">
and username like '%' #{arg0} '%'
</if>
<if test="arg1 > 0">
and role &lt; #{arg1}
</if>
</where>
</select>
</mapper>
一些符号不能使用需要替换
< <= > >= & ' "
&lt; &lt;= &gt; &gt;= &amp; &apos; &quot;

 

choose的行为类似于switch

    <select id="queryByChoose" resultType="User">
        select *
        from user
        <where>
            <choose>
                <when test="arg0 != null and arg0 != ''">
                    and username like '%' #{arg0} '%'
                </when>
                <when test="arg1 > 0">
                    and role &lt; #{arg1}
                </when>
            </choose>
        </where>
    </select>

 

foreach

<select id="quertByForeach" resultType="User">
    select *
    from user
    <if test="array.length > 0">
        where id in
        <foreach collection="array" item="roleid" open="(" close=")" separator=",">
            #{roleid}
        </foreach>
    </if>
</select>

 

foreach-list

<select id="quertByForeachList" resultType="User">
    select *
    from user
    <if test="list.size > 0">
        where id in
        <foreach collection="array" item="roleid" open="(" close=")" separator=",">
            #{roleid}
        </foreach>
    </if>
</select>

 

SQL片段

<sql id="parms">
    id, username, password, role
</sql>
select <include refid="parms"></include>from user

 

一对多

简化版

public class User {
    private Set<Article> articles;
}
public class Article {
    private User author;
}

 

查询

<resultMap id="userMapper" type="com.foreignkeyMybatis.beans.User">
<id column="id" property="id"/>
<result column="username" property="username"/>
<collection property="articles" ofType="com.foreignkeyMybatis.beans.Article">
<id column="aid" property="id"/>
<result column="title" property="title"/>
</collection>
</resultMap>
<select id="getAll" resultMap="userMapper">
select user.id, username, title, uid, aid
from user, article
where uid = user.id
</select>

 

或者也可以

<select id="selectArtByUid" resultType="com.foreignkeyMybatis.beans.Article">
    select title from article where uid=#{xxx}
</select>
<resultMap id="userMapper2" type="com.foreignkeyMybatis.beans.User">
    <id column="id" property="id"/>
    <result column="username" property="username"/>
    <collection property="articles"
                ofType="com.foreignkeyMybatis.beans.Article"
                select="selectArtByUid"
                column="id">
    </collection>
</resultMap>
<select id="getByName" parameterType="string" resultMap="userMapper2">
    select id, username from user where username=#{xxx}
</select>

 当多对一时,只需将collection替换成associate就可以

 

懒加载

mybatis.xml 中配置, 必须是多次查询。

侵入式懒加载

    <settings>
        <!--        访问实体时才触发加载, 实体内的关联表作为实体的一部分-->
        <setting name="lazyLoadingEnable" value="true"/>
        <setting name="aggresiveLayLoading" value="false"/>
    </settings>

 

深度懒加载

    <settings>
        <!--        访问实体内的关联表时才触发加载-->
        <setting name="lazyLoadingEnable" value="true"/>
        <setting name="aggresiveLayLoading" value="true"/>
    </settings>

 

缓存

  1. 一级缓存: 基于PerpetualCache 的 HashMap本地缓存,其存储作用域为 SQLSession,当 Session flush 或 close 之后,该Session中的所有 Cache 就将清空。默认开启

    2.二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap存储,不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache。

 

二级缓存开启

<mapper namespace="com.cache.dao.IUserDao">
  <!-- 开启二级缓存 -->
  <cache/>
</mapper>

常用属性

<cache 
  eviction="FIFO"  <!--回收策略为先进先出-->
  flushInterval="60000" <!--自动刷新时间60s-->
  size="512" <!--最多缓存512个引用对象-->
  readOnly="true"/> 

 

使用ehcache缓存

需要 mybatis-ehcache.jar 和 ehcache-core.jar

<cache type="org.mybatis.caches.ehcache.EhcacheCache">

配置

ehcache.xml

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
  <diskStore path="F:\develop\ehcache" /> 磁盘中的存储位置
  <defaultCache
    maxElementsInMemory="1000"  内存中缓存的element的最大数目 
    maxElementsOnDisk="10000000"  磁盘上缓存的element的最大数目
    eternal="false"  设定缓存的elements是否永远不过期
    overflowToDisk="false"  内存缓存溢出的时候是否将过期的element缓存到磁盘上
    timeToIdleSeconds="120"  两次访问的间隔时间,超过便被删除
    timeToLiveSeconds="120"  缓存element的有效生命期
    diskExpiryThreadIntervalSeconds="120"  磁盘缓存的清理线程运行间隔,默认是120秒
    memoryStoreEvictionPolicy="LRU">  内存缓存达到最大,有新的element加入的时候, 移除缓存中element的策略
  </defaultCache>
</ehcache>