mybatis学习笔记

MyBatis学习

什么是mybatis?
Mybatis是一个半自动的ORM持久层框架,内部封装了JDBC。作为开发者只需要关注sql语句本身。Mybatis是通过xml或注解的方式将需要执行的各种statement配置起来。通过Java对象和statement中的sql动态参数映射生成最终执行的sql语句,最终由Mabtais框架执行sql并将结果映射为Java对象并返回。MyBatis 支持定制化 SQL、存储过程以及高级映射。MyBatis 是可以双向映射的,可以将数据集映射为Java对象,也可以将Java对象映射为数据库中的记录。

使用mybatis框架

mybatis框架需要用xml文件来配置其信息
框架jar包地址链接:https://pan.baidu.com/s/1T-yuDMstY_P1DL-gjkuf0g
提取码:0000
注意,需要sql驱动包(mysql为例),驱动包在jdbc博客中可以找到,还要注意版本匹配问题

<!--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>
<!--    jdbc配置信息-->
    <properties resource="jdbc.properties"></properties>
<!--    打印输出日志信息,需要导入log4j包-->
    <settings>
        <setting name="logImpl" value="LOG4J"/>
    </settings>
    <!--给实体类配置别名-->
    <typeAliases>
        <!--给指定类配置别名,在mapper返回中可以通过别名返回结果集到指定的实体类中-->
        <typeAlias type="com.study.entity.Student" alias="student"></typeAlias>
        <!--包下所有类的别名就是当前类名 类名首字母小写-->
        <package name="com.study.entity"/>
    </typeAliases>
    <!--default属性指向使用哪个连接-->
    <environments default="mysql">
        <!--mysql数据库的连接-->
        <environment id="mysql">
            <transactionManager type="JDBC"></transactionManager>
            <!--底层使用连接池连接数据库-->
            <dataSource type="POOLED">
                <!--连接数据库需要的配置信息                -->
<!--                配置信息解耦合存储在jdbc.properties中,通过properties标签配置文件路径-->
                <property name="driver" value="${m_driver}"/>
                <property name="url" value="${m_url}"/>
                <property name="password" value="${m_password}"/>
                <property name="username" value="${m_username}"/>
            </dataSource>
        </environment>
        <!--oracle数据库的连接-->
        <environment id="oracle">
            <transactionManager type=""></transactionManager>
            <dataSource type=""></dataSource>
        </environment>
    </environments>
    <mappers>
        <!--resource书写的是xml所在目录,扫描mapper.xml文件进行数据库操作-->
        <mapper resource="com/study/mapper/StudentMapper.xml"></mapper>
<!--        扫描包下所有mapper.xml-->
        <package name="com.study.mapper"/>
    </mappers>
</configuration>

配置文件写好,接下来开始写mapper.xml

<!--mapper的约束-->
<?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">
        <!--namespace命名空间,java代码通过此属性调用mapper中的某个查询-->
 <mapper namespace="flower">
 
 	<!--    id属性,是java代码中调用的方法,resultType属性是返回的实体类类型,java中用Object接收-->
    <select id="selectAll" resultType="flower">
        select * from flower
    </select>
    <!--传入对象为实体类 parameterType指定传入的类型(可以省略),使用#{}来获取传入的对象属性,{}内写实体类的属性名-->
    <select id="selectOne3" resultType="flower" parameterType="flower">
        select * from  flower where id=#{id} and name=#{name}
    </select>
	<select id="selectOne4" resultType="flower" parameterType="map">
		<!--{}内的是key键名-->
        select * from  flower where id=#{id} and name=#{name}
        <!--#底层使用占位符? $底层使用的是拼接 相当于statement-->
    </select>
<!--增删改操作,只是标签和sql语句不同,其他一致-->
<insert id="insert" parameterType="flower">
        insert into flower values(default,#{name},#{price},#{production})
    </insert>
    <update id="update" parameterType="flower">
        update flower set name=#{name},price=#{price} where id=#{id}
    </update>
    <delete id="delete">
        delete from flower where id=#{param1}
    </delete>
 </mapper>

下面来写对应的调用mapper的java
步骤和jdbc差不多,需要获取到SqlSession来进行操作

public class TestA {
    public static void main(String[] args){
    	SqlSession session=null;
        try {
            //解析mybatis.xml
            InputStream resourceAsStream = Resources.getResourceAsStream("mybatis.xml");
            //获得session工厂
            SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(resourceAsStream);
            //获取sqlSession对象
            session=factory.openSession();
            //参数对应mapper命名空间和增删改查的对应id
            Object o = session.selectOne("flower.selectAll");//返回值会返回对应的mapper文件resultType属性的类型

		//参数传递传入对象
            Flower flower=new Flower();
            flower.setId(1);
            flower.setName("玫瑰");
            Flower o = session.selectOne("flower", flower);
	
		//参数传递三 map集合
            Map<String,Object> map=new HashMap<>();
            map.put("id",1);
            map.put("name","玫瑰");
            Object om= session.selectOne("flower", map);
            System.out.println(om);
    	} catch (Exception e){
            e.printStackTrace();
        }finally {
            //关闭sqlSession
            if (session!=null){
                session.close();
            }
      }
}

SqlSession的其他方法大同小异可查看api
注意事项:添加、删除、修改操作写好了必须提交
SqlSession.commit();
factory.openSession(true);
parameterType类型可以省略

封装SqlSession

将重复的获取sqlSession的操作封装起来

public class DBUtil {
    private static SqlSessionFactory factory=null;
    //使用ThreadLocal来对SqlSession进行管理
    //此类会在同一个线程中使用同一个SqlSession
    private static ThreadLocal<SqlSession> tl=new ThreadLocal<>();
    //程序一加载就初始化所有需要的类
    static {
        InputStream inputStream=null;
        try {
            inputStream= Resources.getResourceAsStream("mybatis.xml");
            factory=new SqlSessionFactoryBuilder().build(inputStream);
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if (inputStream!=null){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    public static SqlSession getSqlSession(){
        //获得sqlSession对象
        SqlSession session = tl.get();
        if (session==null){
            session= factory.openSession();
            //把创建好的session对象放入threadLocal
            tl.set(session);
        }
        return tl.get();
        //自动提交
        //return factory.openSession(true);
    }
    public static void closeAll(){
        SqlSession session = tl.get();
        if (session!=null){
            session.close();
        }
    }
}

为什么使用ThreadLocal管理可以查看此帖子
链接:https://blog.csdn.net/qq_16696457/article/details/108917103

使用mapper接口

mybatis学习笔记

mapper的接口要和其xml文件名称一致,并且放在同一个包下

//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">
<!--namespace:必须是接口所在的全路径-->
<mapper namespace="com.study.mapper.FlowerMapper1">
    <!--id名称必须和接口方法名称一致-->
    <select id="selectAll" resultType="flower">
        select * from flower
    </select>
    <!--对于有参数的使用param1等进行传参,按照参数顺序进行排序-->
    <select id="selectAll" resultType="flower">
        select * from flower where id=#{param1} and name=#{param2}
    </select>
</mapper>
//接口
public interface FlowerMapper1 {
    List<Flower> selectAll();
    //参数类型可以全是String类型,mysql中字符类型可以查询所有类型数据
     List<Flower> selectAll(String id,String name);
}

mybatis.xml文件中需要配置扫描标签

//java调用
public class TestMapper4 {
    public static void main(String[] args) {
        SqlSession session=null;
        try {
            //解析mybatis.xml
            InputStream resourceAsStream = Resources.getResourceAsStream("mybatis.xml");
            //获得session工厂
            SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(resourceAsStream);
            //获取sqlSession对象
            session=factory.openSession();
            //接口类对象
            FlowerMapper1 mapper = session.getMapper(FlowerMapper1.class);
            List<Flower> flowers = mapper.selectAll();
            System.out.println(flowers);
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            //关闭sqlSession
            if (session==null){
                session.close();
            }
        }
    }
}
OGNL表达式

通过特定标签来进行特殊的查询

<!--where标签-->
    <select id="selectMore2" resultType="flower">
        select * from flower
        <!--OGNL表达式-->
        <!--where标签作用,会自动地增加where关键字,并且会把多余的第一个and去掉-->
        <where>
        <!--if标签 ,进行判断如果为true则添加标签内表达式-->
        <if test="param1!=null and param1!=''">
            name=#{param1}
        </if>
        <if test="param2!=null and param2!=''">
            and production=#{param2}
        </if>
        </where>
    </select>
<!--set标签-->
<update id="update">
        update flower
                          <!--set 会自动增加set关键字,并且去除最后一个逗号-->
        <set>
            <if test="name!=null and name!=''">
                name=#{name},
            </if>
            <if test="production!=null and production!=''">
                production=#{production}
            </if>
        </set>

        where id=#{id}
    </update>
<!--trim标签-->
<update id="update">
        update flower
        <!--
        prefix:添加前缀
        prefixOverrides:去除前缀
        suffixOverrides:去除后缀
        suffix:添加后缀
        -->
        <trim prefix="set" suffixOverrides=",">
            <if test="name!=null and name!=''">
                name=#{name},
            </if>
            <if test="production!=null and production!=''">
                production=#{production}
            </if>
        </trim>

        where id=#{id}
    </update>
<!--choose标签-->
    <select id="selectMore3" resultType="flower">
        select * from flower
        <!--OGNL表达式-->
        <!--where标签作用,会自动地增加where关键字,并且会把多余的第一个and去掉-->
        <where>
            <choose>
                <when test="param1!=null and param1!=''">
                    name=#{param1}
                </when>
                <when test="param2!=null and param2!=''">
                    and production=#{param2}
                </when>
                <otherwise>
                    1=1
                </otherwise>
            </choose>
        </where>
    </select>
<!--foreach标签,用来进行模糊查询-->
	<select id="selectMore" resultType="flower">
        select * from flower where id in
        <!--collection集合类型,open separator close代表前缀后缀和分割 item是集合中每个数据-->
        <foreach collection="list" open="(" separator="," close=")" item="it">
            #{it}
        </foreach>
    </select>
//java代码
public class TestMapper4 {
    public static void main(String[] args) {
        SqlSession session=null;
        try {
            //解析mybatis.xml
            InputStream resourceAsStream = Resources.getResourceAsStream("mybatis.xml");
            //获得session工厂
            SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(resourceAsStream);
            //获取sqlSession对象
            session=factory.openSession();
            FlowerMapper4 mapper = session.getMapper(FlowerMapper4.class);
            List<Integer> list=new ArrayList<>();
            list.add(1);
            list.add(2);
            List<Flower> flowers = mapper.selectMore(list);
            System.out.println(flowers);
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            //关闭sqlSession
            if (session==null){
                session.close();
            }
        }
    }
}

<!--bind标签,用来进行模糊查询-->
<select id="selectMore" resultType="flower">
        select * from flower
        <where>
            <if test="param1!=null and param1!=''">
            <!--bind用于模糊查询-->
                <bind name="pa" value="'%'+param1+'%'" ></bind>
                name like #{pa}
            </if>
            <!--bind标签都可以实现占位符(不会有sql注入) $是进行拼接-->
            <if test="param2!=null and param2!=''">
                and production like '%${param2}%'
            </if>
        </where>
    </select>
resultMap

resultMap是Mybatis最强大的元素,它可以将查询到的复杂数据(比如查询到几个表中数据)映射到一个结果集当中。适合用于多表查询
详细使用参考链接:https://www.cnblogs.com/kenhome/p/7764398.html

<select id="selectAll" resultMap="rm3">
        select * from student join clazz on student.clazzno=clazz.clazz
    </select>
    //id相互对应,type映射的实体类对象
    <resultMap id="rm3" type="student">
    //column查询出来的列字段 property映射到实体类的属性
        <id column="sid" property="sid"></id>
        <result column="sname" property="sname"></result>
        <result column="clazzno" property="clazzno"></result>
        //property实体类中的属性 javaType实体类中关联的实体类属性
        <association property="clazz" javaType="clazz">
            <id column="clazz" property="clazz"></id>
            <result column="cname" property="cname"></result>
        </association>
    </resultMap>

resultMap嵌套

<select id="selectAll" resultMap="rm1">
        select * from student
    </select>
    <resultMap id="rm1" type="student">
        <!--column:数据库的列名 property:实体的属性名-->
        <id column="sid" property="sid"></id>
        <result column="sname" property="sname"></result>
        <result column="clazzno" property="clazzno"></result>
        <!--
        select:执行哪一个方法,执行mapper接口的方法,将结果集需要的列值传入指定的对象
        column:希望查询的哪一列作为参数进行传递
        javaType:返回值类型
        property:把返回的结果赋值给对象中哪一个属性
        -->
        <association select="com.study.mapper.ClazzMapper.selectOne" column="clazzno" javaType="clazz" property="clazz"></association>
    </resultMap>

collection标签

<select id="selectOne" resultMap="rm2">
        select * from clazz where clazz=#{param1}
    </select>
    <resultMap id="rm2" type="clazz">
        <id column="clazz" property="clazz"></id>
        <result column="cname" property="cname"></result>
        <!--ofType返回集合泛型-->
        <collection select="" property="students" ofType="student" column="clazz"></collection>
<!--        注意:<collection>标签中的column:要传递给select查询语句的参数,如果传递多个参数,格式为column= ” {参数名1=表字段1,参数名2=表字段2} ;-->
    </resultMap>

mybatis获取自增主键

<insert id="insert" parameterType="flower" useGeneratedKeys="true">
        insert into flower values(default,#{name},#{price},#{production})
    </insert>
    <!--接口方法传入的参数会接收自增主键的返回,只需要从方法参数中获取即可-->
缓存
<!--启动二级缓存-->
    <cache readOnly="true"></cache>

缓存分为一级二级
一级:sqlsession缓存
二级:factory缓存
sqlSession(先取db,其次从一级缓存取出,当关闭sqlSession时close或者提交时 commit ,一级缓存将会刷入二级缓存)
|
二级缓存 factory
|
一级缓存 sqlSession
|
DB数据库

上一篇:RabbitMQ消息队列保姆级教程


下一篇:微信x5webview接入实战