MyBatis(二)

113 阅读6分钟

Log4j

Log4j是Apache推出的开源免费日志处理的类库。

  1. 为什么需要日志

  • 在项目中编写System.out.println();输出到控制台,当项目发布到Tomcat后,没有控制台了。虽然可以在命令行窗口看见,不方便观察一些输出结果。
  • Log4j不仅能把内容输出到控制太=台,还能把文件输出到文件中,便于观察结果。
  1. 使用步骤

  • 导入log4j-xxx.jar
  • 在src下新建log4j.properties(路径和名称都不允许改变)
log4j.rootCategory=DEBUG, CONSOLE ,LOGFILE

log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%C %p  %m %n

log4j.appender.LOGFILE=org.apache.log4j.FileAppender
log4j.appender.LOGFILE.File=E:/my.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=%C %m %L %n
  1. log4j.properties

  • 信息提示级别

fatal(致命错误)>error(错误)>warn(警告)>info(普通信息)>debug(调试信息)
可以在第一行控制输出级别,如
log4j.rootCategory=DEBUG

  • 输出目的地控制

CONSOLE:控制台
LOGFILE:文件 可以在第一行控制输出目的地 log4j.rootCategory=DEBUG, CONSOLE ,LOGFILE

  • 控制台输出控制

log4j.appender.CONSOLE:由谁控制输出 log4j.appender.CONSOLE.layout:输出格式控制 log4j.appender.CONSOLE.layout.ConversionPattern:具体的表达式内容

  • 文件输出控制

log4j.appender.LOGFILE:由谁控制 log4j.appender.LOGFILE.File:输出地址 log4j.appender.LOGFILE.Append:是否追击,若为false,则每次记录时先清空 log4j.appender.LOGFILE.layout:输出格式控制 log4j.appender.LOGFILE.layout.ConversionPattern:具体的表达式内容

  • 常用的表达式

    表达式 意义
    %C 包名+类名
    %d{YYYY-MM-dd HH:mm:ss} 时间
    %L 行号
    %m 信息
    %n 换行
  • Log4j可以输出指定内容的日志

    • 命名级别:namespace属性最后一项,例如mapper.PeopleMapper,包级别为mapper.
    • 先将整体输出级别改为ERROR,避免输出无用信息。
      log4j.rootCategory=ERROR, CONSOLE ,LOGFILE
    • 设置要输出的级别为DEBUG
      log4j.logger.mapper=DEBUG
  1. setting标签

在Mybatis全局配置文件中,通过setting标签控制Mybatis全局开关。
例如:设置对Log4j日志的支持,需要有jar包和properties文件

<settings>
    <setting name="logImpl" value="LOG4J"/>
</settings>

参数

  1. parameterType

在XXXMapper.xml中的select等标签中的parameterType可以控制参数类型。 2. ### 参数的传递与获取

  • #{}:参数获取
    • #{索引}:通过索引来获取参数,如#{1},从0开始
    • #{param1}:param+索引来获取参数,从1开始
    • 如果只有一个参数,且是基本数据类型或者String,Mybatis对{}中的内容没有要求,只要有东西即可。
    • 如果参数类型为Map,写成#{key}。
  • #{}与${}的区别 实现效果是一样的,底层不一样。前者比较常用,很少使用后者。
    • #{}使用的是?占位符方式,获取参数支持索引、param+索引。
    • ${}使用的是字符串拼接,默认找{}内容的get/set方法,如果是数字,则将数字当成数字处理
  • Sqlsession的selectList()和selectOne()的第二个参数和SelectMap()的第三个参数都表示方法的参数。
    People p = session.selectOne("mapper.selById",1);
  1. 分页

select * from people limit #{},#{}
第一个{}表示从第几个开始,0是第一个。 第二个{}表示查询几个。 ?不允许在关键词前后进行数学运算,需要在Java中算好,将数值传进去。

  1. 别名

别名分为两种。
(1)系统内置别名。一般是把类型全小写。
(2)在全局配置文件中设置,给某个类其别名。

  • 逐个进行配置
<typeAliases>
	<typeAlias type="pojo.People" alias="peo"/>
</typeAliases>
  • 配置整个包的别名,别名为类名,区分大小写
<typeAliases>
	<package name="pojo"/>
</typeAliases>

Mybatis实现新增

功能:从应用程序角度出发,软件具有哪些功能。
业务:完成功能时的逻辑
事务:从数据库角度出发,完成某个业务需要完成的SQL集合,统称一个事务
在Mybatis中默认关闭了JDBC的自动提交功能
Sqlsession.commit()提交事务
openSession(true);自动提交 setAutoCommit(true)
Mybatis底层是对JDBC的封装
JDBC中executeUpdate()执行增删查改,修改的SQL返回值int,表示受影响的行数。 Mybatis中的insert,delete,update标签没有resultType属性,认为返回值是int。

People p = new People();
p.setName = ("恐怖直立猿");
p.setAge = (88);
int index = session.insert("mapper.ins",p);

session.rollback()回滚 可根据int判断,是提交还是回滚

Mybatis接口绑定方案及多参数传递

作用:实现创建一个接口后,能把mapper.xml由Mybatis生成接口的实现类,实现通过调用接口对象就能获取mapper.xml中的SQL
后面Mybatis和SPring整合时也是这个方案 实现步骤

  1. 创建一个接口,要求接口包名与接口名与mapper.xml的namespace一样
  2. 在Mybatis中使用package进行扫描接口和mapper.xml
<mappers>
	<package name="mapper"/>
</mappers>
  1. 接口中方法名和mapper.xml中的方法id相同
  • 接口为什么能实例化?
    需要给接口一个实例化对象。使用的是JDK的动态代理模式,面向接口的代理模式(必须有接口)。
  • 当多参数的时候,不需要写parameterType,直接使用#{索引}或者#{parame+索引}来获取参数,而不能直接用形参名获取参数。
    如果想使用形参名作为参数,需要在接口添加注释@Param("形参名")
    List<X> 方法名(@Param("key")String value 具体用的时候,以注解中的名字寻找。原理是Mybatis会将参数转换为map,注解中的内容作为key,参数内容作为value。

动态SQL

根据条件不同,在mapper.xml中添加逻辑判断,来控制SQL语句。

  • if

<select id="selAll" resultType="pojo.People">
	select * from people where 1=1
	<!-- OGL表达式,直接写key或对象数学,需要添加任何特殊符号 -->
	<if test="name!=null and name !=''" >
		and name=#{name}
	</if>
	<if test="age!=null and age!=''">
		and age=#{age}
	</if>
</select>
  • where

    • 若内容中第一个是and,去掉and。
    • 如果where标签中有内容生成where关键字,否则不生成where关键字
<select id="selAll" resultType="pojo.People">
	select * from people 
	<!-- OGL表达式,直接写key或对象数学,需要添加任何特殊符号 -->
	<where>
		<if test="name!=null and name !='' " >
			and name=#{name}
		</if>
		<if test="age!=null and age!=''">
			and age=#{age}
		</if>
	</where>
</select>
  • choose when otherwise

只有一个城里,其他都不执行 如果name和age都不是空,生成SQL中只有where name=?。

<select id="selAll" resultType="pojo.People">
	select * from people 
	<!-- OGL表达式,直接写key或对象数学,需要添加任何特殊符号 -->
	<where>
	    <choose>
		<when test="name!=null and name !='' ">
		and name=#{name}
		</when>
		<when test="age!=null and age!=''">
		and age=#{age}
		</when>
	    </choose>
	</where>
</select>
  • set用在修改SQL中set从句

    作用:
    • 去掉最后一个逗号
    • 如果set里面有内容生成set关键字,否则不生成
    • id=#{id}是防止set中不生成内容,造成语法错误
<update id="upd">
    update people
	<set>
	    id=#{id},
	        <if test="age!=null and age!=''">
		    age = #{age},
		</if>
		<if test="name!=null and name!=''">
		    name = #{name},
		</if>
		where id=#{id}
	</set>
</update>
  • trim

and,where,trim都是先执行去除,再执行添加
prefix:在前面生成
preOverrides:在前面去掉
suffix:在后面加上
suffixOverides:在后面去掉

<select id="sel" parameterType="People" resultType="People">
	select * from people
	<trim prefix="where" prefixOverrides="and">
		and name=#{name}
	</trim>
</select>

最终生成:select * from people where name=#{name}

  • bind

修饰传来的字符串,常用于模糊查询

<select id="sel">
	<bind name="name" value="'%'+name+'%'"/>
	select * from People where name=#{name}
</select>
  • foreach

循环参数内容,还具备在内容的前后添加内容,还具备添加分隔符功能 适用于:in查询中,批量新增(foreach效率不高) collection:要遍历的集合 item:迭代变量,#{迭代变量名}获取内容 open:循环开始后左侧添加的内容 colse:循环开始后右侧添加的内容 separator:每次循环元素之间的分隔符

<select id="sel" parameterType="list" resultType="People">
	select * from People where id in
	<foreach collection="list" item="a" open="(" close=")" separator=",">
		#{a}
	</foreach>
</select>