003接口绑定方案和多参数传递+动态SQL+ThreadLocal+缓存

一.接口绑定方案和多参数传递

作用:实现创建一个接口后把mapper.xml由mybatis生成接口的实现类,通过调用接口对象就可以获取mapper.xml中编写的sql。后面mybatis和spring整合时使用的就是这个方案。

实现步骤:①创建一个接口,接口包名和接口名与mapper.xml中<mapper>namespace相同,接口中方法名和mapper.xml标签的id属性相同。②在mybaits.xml中使用<package>进行接口扫描和mapper.xml。

代码实现步骤:①在mybatis.xml中<mapper>下使用<package>。②在com.bjsxt.mapper下新建接口。③在com.bjsxt.mapper新建一个LogMapper.xml,namespace必须和接口全限定路径(包名+类名)一致,id值必须和接口中方法名相同,如果接口中方法为多个参数,可以省略parameterType。

<mappers>
	<package name="com.bjsxt.mapper"/>
</mappers>
/**
* mybatis把参数转换为map了,其中@Param("key") 参数内容就是map的value
* @param accin1
* @param accout1
* @return
*/
List<Log> selByAccInAccout(@Param("accin") String accin1,@Param("accout") String accout1);
<!-- 当多参数时,不需要写parameterType -->
<select id="selByAccInAccout" resultType="log" >
	select * from log where accin=#{accin}  and accout=#{accout}
</select>
LogMapper logMapper = session.getMapper(LogMapper.class);

多参数实现办法:①在接口中声明方法,在mapper.xml中添加#{}中使用0,1,2或param1,param2。②可以使用注解方式,在接口中声明方法,在mapper.xml中添加#{}里面写@param("内容")参数中内容。

二.动态SQL

根据不同的条件需要执行不同的SQL命令,称为动态SQL。Mybatis中动态SQL在mapper.xml中添加逻辑判断等。

<if>标签的使用

<select id="selByAccinAccout" resultType="log">
	select * from log where 1=1
	OGNL表达式,直接写key或对象的属性.不需要添加任何特字符号
	<if test="accin!=null and accin!=''">
		and accin=#{accin}
	</if>
	<if test="accout!=null and accout!=''">
		and accout=#{accout}
        </if>
</select>

<where>标签的使用:当编写where标签时,如果内容中第一个是and去掉第一个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>

<choose><when><otherwise>标签的使用:只要有一个成立,其他都不执行。如果accin和accout都不是null或不是""生成的sql中只有where accin=?

<select id="selByAccinAccout" resultType="log">
	select * from log 
	<where>
		<choose>
			<when test="accin!=null and accin!=''">
				and accin=#{accin}
			</when>
			<when test="accout!=null and accout!=''">
			    and accout=#{accout}
			</when>
		</choose>
	</where>
</select>

<set>标签用在修改SQL中的set从句:去掉最后一个逗号,如果<set>里面有内容生成set关键字,没有就不生成。id=#{id}目的防止<set>中没有内容,mybatis不生成set关键字,如果修改中没有set从句SQL语法错误。

<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>

<trim>标签的使用:prefix在前面添加内容,prefixOverrides去掉前面的内容,suffix在后面添加内容,suffixOverrides去掉后面的内容,先去掉内容后添加内容。

<select id="selByLog" parameterType="log" resultType="log">
	select * from log
	<trim prefix="where" prefixOverrides="and">
        and accin=#{accIn}
    </trim>
</select>

<bind>标签的使用:给参数重新赋值,用于模糊查询,在原内容前或后添加内容。

<select id="selByLog" parameterType="log" resultType="log">
	<bind name="accin" value="'%'+accin+'%'"/>
</select>

<foreach>标签的使用:循环参数内容,还具备在内容的前后添加内容,还具备添加分隔符功能,适用于in查询,批量新增中(mybatis中foreach效率比较低)。如果新网批量新增SQL命令,openSession()中必须指定factory.openSession(ExecutorType.BATCH);,底层JDBC的PreparedStatement.addBatch();。collection=""要遍历的集合,item迭代变量,#{迭代变量名}获取内容,open循环后左侧添加的内容,close循环后右侧日安家元素的内容,separator每次循环时,元素之间的分隔符。

<select id="selIn" parameterType="list" resultType="log">
	select * from log where id in
	<foreach collection="list" item="id" open="(" close=")" separator=",">
		#{id}
	</foreach>
</select>
<insert id="ins" parameterType="list">
	insert into log values
	<trim suffixOverrides=",">
		<foreach collection="list" item="log">
			(default,#{log},2,2),
		</foreach>
	</trim>
</insert>

<sql>和<include>标签:某些SQL片段如果希望复用,可以使用<sql>定义这个片段。在<select>或<delete>或<update>或<insert>中引用。

<select id="">
	 select <include refid="mysql"></include>
	 from log
</select>
	
<sql id="mysql">
	id,accin,accout,money
</sql>

三.ThreadLocal

线程容器,给线程绑定一个Object内容后只要线程不变,可以随时取出,如果改变 线程内容无法取出,经过过滤器线程不变。

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);
	}
}
@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);
			session.commit();
		} catch (Exception e) {
			session.rollback();
			e.printStackTrace();
		}finally{
			MyBatisUtil.closeSession();
		}
	}

	@Override
	public void destroy() {	
	}
}

四.缓存

应用程序和数据库交互的过程是一个相对比较耗时的过程,缓存存在的意义是让应用程序减少对数据库的访问,提升程序运行效率。Mybatis中默认SqlSession缓存开启,同一个SqlSession对象调用同一个<select.>时,只有第一次访问数据库,第一次之后把查询结果缓存到SqlSession缓存区(内存)中,缓存的是statement对象(简单记忆必须是用一个<select>),在mybatis时一个<select>对应一个statement对象,有效范围必须是同一个SqlSession对象。

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

SqlSessionFactory缓存:又叫二级缓存,有效范围是同一个factory内哪个SqlSession都可以获取,当数据频繁被使用,很少被修改时使用二级缓存。使用二级缓存步骤:①在mapper.xml中添加<cache readOnly="true"></cache>②当SqlSession对象close()时或commit()时会把SqlSession缓存的数据刷(flush)到SqlSessionFactory缓存区中。

发布了23 篇原创文章 · 获赞 7 · 访问量 1792

猜你喜欢

转载自blog.csdn.net/weixin_44145972/article/details/102517087