mybatis笔记
mybatis约定:
输入参数parameterType 和 输出参数resultType都只能有一个,可以将其写为数组或集合,
或者对象。
如果输入/输出为最简单类型(8个基本类型+String)是可以使用任何占位符,#{xxxx}如果
是对象类型,则必须是对象的属性<如学生:属性:name(名字),则用#{name}表示>
如果用的是jdbc则需要开启事务,提交事务,关闭事务
输出参数如果返回值类型是一个对象(Student),则无论是一个,还是多个resultType都写为
包名加类名不带class
输入参数:parameterType
1.类型为简单类型
#{任意值}(建议别乱写)
${value},其中的标识符只能是value
#{}自动给String类型加上单引号
${}原样输出,但是适合于动态排序(动态字段)
2.对象类型
#{属性名}
${属性名}
#{}可以防止sql注入
${}不能防止sql注入
在模糊查询中,因为#{}是自动加入‘’所以要在这之前对要查询字段改为%x%,而${}原样输出
所以‘%${}%’
输入的参数可以从对象改为HasMap,用map中的key的值 匹配mapper.xml文件的占位符#{}。
value对应的是传入的值。
statementType=CALLABLE(存储过程)
sql存储过程查询的好处:
存储过程 可以同时执行 多条sql语句 而且存储过程要比通常的sql语句要快 可以向里面传进参
数 和 传出参数
性能好,相比于在外面一条一条执行语句,效率会高很多,因为存储过程都是编译好的底层代
码。调用也很简单,可以减轻客户端开发成本
例子:
create procedure UserInfo
@TitleName nvarchar(50),//串进参数
@Content nvarchar(Max),
@PostTime datetime(8),
@Username nvarchar(50),
@TitleID int output
as//sql语句集
declare @newid int
insert into Titles(Titlename,Username,PostTime) values(@TitleName,@Username,@PostTime)
select @newid=max(id) from Titles
insert into TieZiDetail(TitleID,Username,PostTime,Content) values(@newid,@Username,@PostTime,@Content)
select @TitleID=@newid
输出参数resultType:
输出参数为简单类型
输出参数为实体对象类型
输出参数为实体对象类型的集合
输入参数parameterType:
输入参数为集合:
#{ids}
test中就为list collection也只能为list
输入参数为数组:<if test="array != null and array.length">
<foreach collection="array" open="and s.id not in(" close=")" item="ids" separator=",">
#{ids}
</foreach>
test中就为array collection也只能为array
关联查询
一对一:
SELECT
s.,c.
FROM
student AS s
INNER JOIN
card AS c
ON
s.card_id = c.id
WHERE
s.card_id = #{id}
<resultMap type="online.shixun.project.pojo.Card" id="MyCard">
<id column="id" property="id"></id>
<result column="num" property="num" />
<association property="student"
javaType="online.shixun.project.pojo.Students">
<id column="id" property="id"></id>
<result column="name" property="name" />
<result column="classes" property="classes" />
<result column="card_id" property="cardId" />
</association>
</resultMap>
其中column与property看mybatis.png图片!如果遇见重名属性则需要用别名区分!column为数据库的列名或者列标签别名,
property为数据库列的字段或属性!
一对多:
在一对多中,外键的建设在多的一方。怎样建立两个实体间的关联,这里举个例子:
StudentClass类(一方):
// 学生班级id
private int id;
// 学生班级名称
private String name;
// 班级所对应的学生
private Set<Students> student;
Students类(多方):
//学生id
private int id;
//学生名字
private String name;
//学生班级
private String classes;
//学生证id
private int cardId;
//学生证对象
private Card card;
//学生班级id
private int studentIds;
//学生班级对象
private StudentClass studentClass;
在一方建立一个可以获取多方数据的集合,多方建立一个一方的对象。这样就形成了双向的关系,双发均可获取对方数据!
如需单向那就在需要的一方建立关系就可,单向也是这样!
mapper.xml的编写:
StudentClassMapper.xml:
<resultMap type="StudentClass" id="MyStudentClass">
<id column="id" property="id"></id>
<result column="name" property="name" />
<collection property="student" ofType="online.shixun.project.pojo.Students">
<id column="sid" property="id"></id>
<result column="sname" property="name"/>
<result column="classes" property="classes"/>
<result column="card_id" property="cardId"/>
</collection>
</resultMap>
StudentsMapper.xml:
<resultMap type="online.shixun.project.pojo.Students" id="myStudents">
<id column="id" property="id"></id>
<result column="name" property="name" />
<result column="classes" property="classes" />
<result column="card_id" property="cardId" />
<result column="student_ids" property="studentIds" />
<association property="studentClass"
javaType="online.shixun.project.pojo.StudentClass">
<id column="sid" property="id"></id>
<result column="sname" property="name" />
</association>
</resultMap>
日志:Log4j
(jar包)
SLF4J>Apache Commons Logging>Log4j 2> Log4j>JDK logging
开启日志,
如果不指定,Mybatis就会根据以下顺序 寻找日志
(jar包)
SLF4J>Apache Commons Logging>Log4j 2> Log4j>JDK logging
日志级别:
、
log4j定义了8个级别的log(除去OFF和ALL,可以说分为6个级别),优先级从高到低依次为:OFF、FATAL、ERROR、WARN、INFO、DEBUG、TRACE、 ALL。
ALL 最低等级的,用于打开所有日志记录。
TRACE designates finer-grained informational events than the DEBUG.Since:1.2.12,很低的日志级别,一般不会使用。
DEBUG 指出细粒度信息事件对调试应用程序是非常有帮助的,主要用于开发过程中打印一些运行信息。
INFO 消息在粗粒度级别上突出强调应用程序的运行过程。打印一些你感兴趣的或者重要的信息,这个可以用于生产环境中输出程序运行的一些重要信息,但是不能滥用,避免打印过多的日志。
WARN 表明会出现潜在错误的情形,有些信息不是错误信息,但是也要给程序员的一些提示。
ERROR 指出虽然发生错误事件,但仍然不影响系统的继续运行。打印错误和异常信息,如果不想输出太多的日志,可以使用这个级别。
FATAL 指出每个严重的错误事件将会导致应用程序的退出。这个级别比较高了。重大错误,这种级别你可以直接停止程序了。
OFF 最高等级的,用于关闭所有日志记录。
如果将log level设置在某一个级别上,那么比此级别优先级高的log都能打印出来。例如,如果设置优先级为WARN,那么OFF、FATAL、ERROR、WARN 4个级别的log能正常输出,而INFO、DEBUG、TRACE、 ALL级别的log则会被忽略。Log4j建议只使用四个级别,优先级从高到低分别是ERROR、WARN、INFO、DEBUG。
从我们实验的结果可以看出,log4j默认的优先级为ERROR或者WARN(实际上是ERROR)。
建议:在开发时设置debug,在运行时设置为info以上
可通过日志信息,相信的阅读mybatis执行情况(观察mybatis的实际执行sql语句 以及sql中的参数 和返回结果)
延迟加载:
一对一、一对多、多对一、多对多:
一对多:班级——学生>如果不参用延迟加载(立即加载),查询时会将一 和 多的都查询,班级、班级中的所有学生。
如果想要 暂时只查询1的一方,多的一方暂时不查询,而是在需要时在查询。
实现延迟加载的配置文件如下:
StudentClassMapper.xml(一方):
<!-- 根据班级id查询学生信息,懒加载 -->
<select id="queryStudentClassLazy" parameterType="StudentClass" resultMap="myStudentsinfoLazy">
<!-- 先查询班级id获取班级信息 -->
SELECT
s.*
FROM
student_class AS s
WHERE
s.id = #{id}
</select>
<!-- 根据班级id查询学生信息,懒加载 -->
<resultMap type="StudentClass" id="myStudentsinfoLazy">
<id column="id" property="id"></id>
<result column="name" property="name" />
<!--学生,通过select在需要的时候在查学生 -->
<collection property="student" ofType="online.shixun.project.pojo.Students"
select="online.shixun.project.mapper.StudentMapper.queryStudnet" column="id">
</collection>
</resultMap>
StudentMapper.xml(多方):
<!-- 根据班级所有学生信息 -->
<select id="queryStudnet" resultType="online.shixun.project.pojo.Students">
SELECT
s.*
FROM
student AS s
WHERE
s.student_ids = #{studentIds}
</select>
其中select指的是xml的路径加上查询语句的id,column指的是外键~!
一级缓存:
同一个SqlSession队象,MyBatis默认开启一级缓存,如果用同一个SqlSession队象查询相同的数据则只会在第一次查询时向
数据发送sql语句,并将结果放入到SqlSession中(作为缓存存在)后续再次查询该对象时,则会直接从缓存中查询该对象即可!
二级缓存:
Mybatis自带二级缓存:不同SqlSession队象是否来自同一namespace!如果来自同一个namespace!则这些对象共享二级缓存
禁用:在要禁用的查询语句里中将useCache设置为:false就行了!!
存在的问题:
一、由于二级缓存的数据不一定都是存储到内存中,它的存储介质多种多样,所以需要给缓存的对象执行序列化。如果该
类存在父类,那么父类也要实现序列化。
二、springboot在开启二级缓存的情况下,查,增(删、改),查时会有脏数据的产生,并没有及时将缓存中的数据进行更新。
缓存名中率:第一次为0.0,第二次为0.5,第三次就为2/3,依次类推下去!
序列化:内存-->硬盘
硬盘-->内存
第三方提供的二级缓存:ehcache/memcache
要想整合第三方提供的二级缓存(或是自己定义的二级缓存),必须实现org.apache.ibatis.cache.Cache接口,该接口的默认实现类
为PerpetualCache.
整合ehcache二级缓存:
Ehcache-core.jar
mybatis-Ehcache.jar
slf4j-api.jar以上为所需jar包