欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Mybatis笔记

程序员文章站 2022-06-02 13:14:28
Mybatis开始 SQL语句输出方式 1.在全局配置文件中,配置标签 2.使用log4j等工具,进行输出 mapper中传递参数方式 #{}和${}的区别 #{}表示占位符的方式拼接sql语句 占位符为"?" ${}表示拼接字符串的方式拼接sql语句 ${}很少用 全局配置文件解释 1.1

mybatis开始

sql语句输出方式

1.在全局配置文件中,配置标签

    <settings>
        <setting name="logimpl" value="stdout_logging"/>
    </settings>

2.使用log4j等工具,进行输出

mapper中传递参数方式

#{}和${}的区别 #{}表示占位符的方式拼接sql语句 占位符为"?" ${}表示拼接字符串的方式拼接sql语句 ${}很少用

<select id="selall" resulttype="com.bjsxt.pojo.people" parametertype="int">
        select *from people where id=#{0} //传入参数为 的时候 使用索引 占位符选择0位置第一个参数   当传入参数只有一个的时候,#{}大括号中内容可以位任意字符
        select *from people where id=#{param1}//param+数字表示第几个参数,从1开始
        select *from people where id=#{0}//此时不使用索引  单纯的id=0
</select>
<select id="selall" resulttype="com.bjsxt.pojo.people" parametertype="com.bjsxt.pojo.people">
        select *from people where id=#{id}
        select *from people where id=${id}//若使用拼接字符串方式,则需要传入为对象,mybatis自动在传入的对象中寻找对应名字的getset方法来获取值
</select>
<select id="selall" resulttype="com.bjsxt.pojo.people" parametertype="java.util.map">
        select *from people where id=#{key} //#{}中填写map的key
</select>

全局配置文件解释

1.1 <transactionmanager/> type 属性可取值 1.1.1 jdbc,事务管理使用 jdbc 原生事务管理方式 1.1.2 managed 把事务管理转交给其他容器,如交给spring进行管理.原生jdbc 事务 setautomapping(false); 1.2 <datasouce/>type 属性 1.2.1 pooled 使用数据库连接池 1.2.2 unpooled 不实用数据库连接池,和直接使用 jdbc 一样 1.2.3 jndi :java 命名目录接口技术.

例子:

<configuration>
    <!-- default引用environment的id,当前所使用的环境 -->
    <environments default="default">
        <!-- 声明可以使用的环境 -->
        <environment id="default">
            <!-- 使用原生jdbc事务 -->
            <transactionmanager type="jdbc"></transactionmanager>
            <datasource type="pooled">
                <property name="driver" value="com.mysql.jdbc.driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/ssm"/>
                <property name="username" value="root"/>
                <property name="password" value="yu752949273"/>
            </datasource>
        </environment>
    </environments>

 

绝对路径

如果是请求转发 / 表示项目根目录(webcontent) 其他重定向,<img/> <script/>,<style/>,location.href 等/都表示服务器根目录(tomcat/webapps 文件夹) 如果客户端请求的控制器,控制器转发到jsp后,jsp中如果使用相对路径,需要按照控制器的路径去找其他资源. 尽量使用绝对路径 避免相对路径与控制器路径冲突的问题

 

mybatis与ibatis的区别

版本

2.x为ibatis 3.x为mybatis

全局配置文件中

ibatis中使用sqlmap元素,mybatis中使用mappers元素 ibatis中根元素是sqlmapconfig,mybatis中是configuration settings中属性配置不同

ibatis中为

<settings 属性1="属性值1" 属性2="属性值2"  属性x="属性值x"/>

mybatis中为

<settings>

<setting name="属性1" value="属性值1"/>

<setting name="属性2" value="属性值2"/>

<setting name="属性x" value="属性值x"/>

</settings>

映射文件中

ibatis中使用sqlmap元素,mybatis中使用mapper元素

resultmap

当返回值类型为resultmap时,需要在mapper中编写resultmap与实体类中的属性向映射,其中 一对一association 一对多,多对多collection

<association property="" column="" select=""></association>  <!--property为映射实体类中属性 column为数据库中属性列 select为子查询id-->
<collection property="" column="" oftype="" select=""></collection> <!--property为映射实体类中属性 column为数据库中属性列 select为子查询id  oftype为另一对多的实体类-->

动态sql

标签

<where>   <set>   <if test="a!=null and a!=''">   <trim>   <bind>   <choose><when><otherwise>    <sql><include>   <foreach>
<where>标签

先去掉条件的第一个and 然后添加where 当where中的条件不存在时 where标签也不存在

<select id="selbyaccinaccout" resulttype="log">
    select * from log
        <where>
            <if test="accin!=null and accin!=''"> 
                and accin=#{accin}
            </if>
            <if test="accout!=null and accout!=''">
                and accout=#{accout}
            </if>
        </where>
</select>
<set>标签

先去掉条件的最后一个逗号 然后在最前面添加set 当set中的条件不存在时 set标签也不存在

<update id="upd" parametertype="log" >
update log
    <set>
        id=#{id},
        <if test="accin!=null and accin!=''">
            accin=#{accin},
        </if>
        <if test="accout!=null and accout!=''">
            accout=#{accout},
        </if>
    </set>
where id=#{id}
</update>
<if>标签

若不满足条件则该字句不存在 test等于的字符串中,若条件为多个,则用and或or连接 不是&或|

<if test="accin!=null and accin!=''">
and accin=#{accin}
</if>
<trim>标签

prefix 在前面添加内容 prefixoverrides 去掉前面内容 suffix 在后面添加内容 suffixoverrieds 去掉后面内容 执行顺序为 先去掉内容 再添加内容

<update id="upd" parametertype="log">
    update log
        <trim prefix="set" suffixoverrides=",">
            a=a,
        </trim>
    where id=100
</update>
<bind>标签

为传递的变量拼接字符

<bind name="aaa" value="'$'+aaa"/>
<choose><when><otherwise>标签
    <choose>
        <when test="a!=null">
        </when>
    </choose>
    <choose>
        <when test="b!=null">
        </when>
    </choose>

只要有一个成立,其他都不执行. 若存在多个能够成立的,则只执行成立的第一个

<sql><include>标签

sql片段 复用 <sql id="a"></sql> <include refid="a"></include>

<foreach>标签
<foreach collection="" item="" index="" open="" close="" separator="">

</foreach>

collection-要遍历的集合 item-表示在迭代过程中每一个元素的别名 index-迭代位置 open-以什么开始 close-以什么结束 separator-以什么分隔

threadlocal线程容器

给线程绑定一个object容器,若线程状态不变则可以随时取出,若线程发生改变,则无法取出.

final threadlocal<string> threadlocal = new threadlocal<>();
threadlocal.set("测试");
new thread(){
    public void run() {
    string result = threadlocal.get();
    system.out.println("结果:"+result);//线程改变无法取出
    };
}.start();
string result = threadlocal.get();
system.out.println("结果:"+result);//可以取出

主要用于同一servlet线程,静态加载sqlsessionfactory

工具类:

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 mybatisutil {
    //factory实例化的过程是一个比较耗费性能的过程.
    //保证有且只有一个factory
    private static sqlsessionfactory factory;
    private static threadlocal<sqlsession> tl = new threadlocal<>();
    static{
        try {
            inputstream is = resources.getresourceasstream("mybatis.xml");
            factory = new sqlsessionfactorybuilder().build(is);
        } catch (ioexception e) {
            // todo auto-generated catch block
            e.printstacktrace();
        }
    }
    /**
     * 获取sqlsession的方法
     */
    public static sqlsession getsession(){
        sqlsession session = tl.get();
        if(session==null){
            tl.set(factory.opensession());
        }
        return tl.get();
    }
    
    public static void closesession(){
        sqlsession session = tl.get();
        if(session!=null){
            session.close();
        }
        tl.set(null);
    }
}

 

拦截器:

import java.io.ioexception;
import java.io.inputstream;
import javax.servlet.filter;
import javax.servlet.filterchain;
import javax.servlet.filterconfig;
import javax.servlet.servletexception;
import javax.servlet.servletrequest;
import javax.servlet.servletresponse;
import javax.servlet.annotation.webfilter;
import org.apache.ibatis.io.resources;
import org.apache.ibatis.session.sqlsession;
import org.apache.ibatis.session.sqlsessionfactory;
import org.apache.ibatis.session.sqlsessionfactorybuilder;
import com.bjsxt.util.mybatisutil;
/**
 * 最开始是由spring框架提出的.整合hibernate框架是使用的是opensessioninview
 * 
 * 
 * @author administrator
 *
 */
@webfilter("/*")
public class opensessioninview implements filter{
    @override
    public void init(filterconfig filterconfig) throws servletexception {   
    }
    @override
    public void dofilter(servletrequest servletrequest, servletresponse servletresponse, filterchain filterchain)
            throws ioexception, servletexception {  
        sqlsession session = mybatisutil.getsession();
        try {
            filterchain.dofilter(servletrequest, servletresponse);//允许servlet执行,而允许service执行
            session.commit();
        } catch (exception e) {
            session.rollback();
            e.printstacktrace();
        }finally{
            mybatisutil.closesession();
        }
    }
    @override
    public void destroy() {
    }
}

缓存

mybatis 中默认 sqlsession 缓存开启

sqlsession 缓存必须是同一个sqlsession 对象

同一个 sqlsession 对象调用同一个时,只有第一次访问数据库,第一次之后把查询结果缓存到 sqlsession 缓存区(内存)中

缓存流程

步骤一: 先去缓存区中找是否存在 statement(<select>) 步骤二:返回结果 步骤三:如果没有缓存 statement 对象,去数据库获取数据 步骤四:数据库返回查询结果 步骤五:把查询结果放到对应的缓存区中

sqlsessionfactory 缓存

比 sqlsession 缓存高一级的二级缓存,默认关闭 开启方法再mapper.xml的mapper中添加标签:

<mapper namespace="com.bjsxt.mapper.logmapper">
<cache readonly="true"></cache>
    <insert id="ins" parametertype="log">
        insert into log values(default,#{accout},#{accin},#{money})
    </insert>
</mapper>

只有当sqlsession在commit()或close()的时候才会将sqlsession缓存提交到sqlsessionfactory缓存中

mybatis运行原理

运行过程中需要用到的类:

resource 加载mybatis全局配置文件的io流工具

sqlsessionfactorybuilder() 创建sqlsessionfactory接口的实现类

xmlconfigbuilder 读取全局配置文件的流内容,转换为java代码

configuration 由xmlconfigbuilder 创建,封装了全局配置文件中所有的属性信息

defaultsqlsessionfactory 是sqlsessionfactory接口的实现类

transaction 事务类 每一个session都会创建一个transaction对象进行事务管理

transactionfactory 事务工厂,负责生产事务类

executor mybatis执行器 一般使用simpleexecutor实现类,批量操作时,使用batchexecutor 通过opensession的参数控制 负责执行sql命令 相当于jdbc 中的statement对象或preparedstatement对象或callablestatement对象

mybatis结束