Mybatis笔记
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对象