前情回顾
这里写目录标题
${} 与 #{}区别
#{}
@Select("select * from Student where SID=#{sid}")
public Student getStudentBySID(int sid);
Preparing: select * from Student where SID=?
Parameters: 2(Integer)
#{}处理方式类似于preparedStatement参数的操作将占位符替换为 ?,使用的参数必须提供了getter,将SQL语句和参数值分开传到服务器.
优点:不存在SQL注入的问题
${}
@Select("select * from Student where SID=${SID}")
public Student getStudentBySID(Student student);
Preparing: select * from Student where SID=1
Parameters:
${}类似于jdbc中statement直接将参数拼接到SQL语句之中
缺点:存在SQL注入的问题
typeAliases标签
Tip:typeAliases在mybatis-config.xml中配置(主配置文件)
<!--类型别名-->
<typeAliases>
<!--单个别名定义 type:pojo类的路径(全限定名) alias:别名的名称-->
<typeAlias type="com.tulun.MybatisDemo.Student" alias="student"/>
<!--批量的别名定义 name:指定的包名,将包下边的所有pojo类取别名,别名为类名(首字母大小写都行)-->
<package name="com.tulun.pojo"/>
</typeAliases>
业务场景:极大的简化了配置文件的编写,当工作量比较大的时候可以配置resultType和parameterType Windows中别名可以不关注大小写。
动态SQL
if标签
<select id="selectStudent" resultType="com.bean.student">
select * from student where 1=1
<if test="Sage != 0">
and Sage = #{Sage}
</if>
</select>
使用log4j.properties可以看见一下结果
假如传两个参数 :select * from Student where 1=1 and Sage = #{Sage} and Ssex = #{Ssex}
假如传一个参数:select * from Student where 1=1 and Sage = #{Sage}
## debug 级别
log4j.rootLogger=DEBUG,Console
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.Target=System.out
log4j.appender.Console.layout = org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%d{yyyy-MM-dd-HH\:mm\:ss,SSS} [%t] [%c] [%p] - %m%n
log4j.logger.com.mybatis=DEBUG /
##输出sql 语句
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
trim标签
trim标签作用取出SQL中多余And关键字,逗号,使用在where或者set
<select id="updateStudent" resultType="com.conn.student">
update student
<trim prefix="set" suffixOverrides=",">
<if test="Sage != null">
Sage = #{Sage},
</if>
<if test="name != null">
Sname = #{name},
</if>
</trim>
where SID = #{SID}
</select>
属性 | 描述 |
---|---|
prefix | 给SQL拼接前缀 |
suffix | 给SQL拼接后缀 |
prefixOverrids | 剔除SQL语句前缀字符 |
suffixOverrids | 剔除SQL语句后缀字符 |
where标签
<select id="findStudent1" resultType="com.bean.student">
select * from student
<where>
Sname = #{name}
</where>
</select>
省去了多余的1 = 1的条件
foreach标签
<select id="findStudent1" resultType="com.bean.student">
select * from student
<where>
<if test="list != null">
<foreach collection="list" separator="," close=")" open="and SID in(" item="id">
#{id}
</foreach>
</if>
</where>
</select>
属性 | 描述 |
---|---|
collection | 所要遍历集合的名称 |
separator | 集合之中分割符 |
close | 结束的字符 |
open | 开始的字符 |
item | 集合之中的单个字符名称 |
collection可以使用与List、Map、数组等等
模糊匹配
模糊匹配一共有三种方式
直接传入%s%
<select id="studentByName" resultType="com.conn.student">
select *from student where Sname like #{name}
</select>
使用concat方法
<select id="studentByName" parameterType="java.lang.String" resultType="com.conn.student">
select *from student where Sname like concat('%',concat(#{name},'%'))
</select>
使用bind标签
<select id="studentByName" resultType="com.conn.student">
<bind name="s" value="'%'+name+'%'"/>
select *from student where Sname like #{s}
</select>
缓存机制
一级缓存
mybatis中一级缓存是不需要任何的配置,是sqlsession级别的查询
执行同一个SQL语句第一次查询对应的信息,当第二次查询的时候优先去缓存区查询对应的结果
这个图片可以看到第一次进行了SQL查询,第二次直接在缓存区查询
这里可以看出当对对应的数据库字段做出改变是,缓存区立马被清空,第二次查询只能继续访问数据库
不同session执行缓存不共享
二级缓存
二级缓存是mapper级别的,默认的是关闭的需要手动的开启
主配置文件配置
<settings>
<!--开启二级缓存的开关-->
<setting name="cacheEnabled" value="true"/>
</settings>
映射文件配置
<!--开启本Mapper的二级缓存-->
<cache></cache>
同一个mapper不同SQLSession下的查询可以看出共享缓存
高级映射
一对一
association:用于映射关联查询单个对象的信息
<mapper namespace="com.dao.ordersDao">
<resultMap id="OrderUserResultMap" type="com.bean.orders" >
<!--
property:关联查询映射到对应的自定义的对象的属性
javaType:映射的Java属性的全限定名
columnPrefix:给数据库字段添加前缀
-->
<id column="id" property="id"/>
<result column="user_id" property="user_id"/>
<result column="number" property="number"/>
<result column="date" property="date" javaType="java.util.Date" jdbcType="TIMESTAMP"/>
<result column="note" property="note"/>
<association property="user" columnPrefix="u_" javaType="com.bean.user">
<!--user配置-->
<result column="id" property="id"/>
<result column="username" property="username"/>
<result column="sex" property="sex"/>
<result column="address" property="address"/>
</association>
</resultMap>
<select id="findAll" resultMap="OrderUserResultMap">
select o.*,u.id u_id,u.username u_username,u.sex u_sex,u.address u_address from orders o,user u where o.user_id = u.id
</select>
</mapper>
这里需要注意当SQL语句太长换行的时候在前一段末尾或下一段前面加一个空格因为在拼接字符串的时候会将两个关键词拼接在一起
使用extends关键词简化xml配置的编写
<resultMap id="orderResultMap" type="com.bean.orders">
<!--orders配置-->
<id column="id" property="id"/>
<result column="user_id" property="user_id"/>
<result column="number" property="number"/>
<result column="date" property="date" javaType="java.util.Date" jdbcType="TIMESTAMP"/>
<result column="note" property="note"/>
</resultMap>
<resultMap id="userResultMap" type="com.bean.user">
<!--user配置-->
<result column="id" property="id"/>
<result column="username" property="username"/>
<result column="sex" property="sex"/>
<result column="address" property="address"/>
</resultMap>
<resultMap id="OrderUserResultMap" type="com.bean.orders" extends="orderResultMap">
<association property="user" columnPrefix="u_" javaType="com.bean.user" resultMap="userResultMap"></association>
</resultMap>
这里需要注意:当xml配置映射关系比较多的时候使用extends关键词可以极大节省开发时间,也可以是代码变得简洁起来,通俗说哪里需要用到直接可以使用extends关键词使用
一对多
使用collection可以将用户一对多订单映射到集合之中
<resultMap id="userMap" type="com.bean.user" extends="userResultMap">
<collection property="orders" columnPrefix="order_" ofType="com.bean.orders" resultMap="orderResultMap"></collection>
</resultMap>
<!--这块可以实现代码的复用当下一次使用的时候直接可调用-->
<sql id="selectId">
u.id,
u.username,
u.sex,
u.address,
o.id order_id,
o.user_id order_user_id,
o.number order_number,
o.createtime order_createtime,
o.note order_note
</sql>
<select id="findStudentIds" parameterType="int" resultMap="userMap">
select <include refid="selectId"/>
from user u ,orders o where u.id=o.user_id and u.id=#{uid};
</select>
延时加载
开启延时加载
<!-- 开启延迟加载 -->
<settings>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.dao.ordersDao">
<!-- 定义可以封装带有User的order的 resultMap -->
<resultMap id="orderWithUserMap" type="com.bean.orders" extends="orderResultMap">
<!-- 关联 User 对象 -->
<association property="user" javaType="com.bean.user" column="user_id" select="com.dao.userDao.findStudentIds"></association>
</resultMap>
<!-- 配置查询所有订单,延迟加载用户信息 -->
<select id="findAll" resultMap="orderWithUserMap">
SELECT * FROM orders
</select>
</mapper>
这里需要注意select关联查询的已存在的方法的全路径
association中的column是接口的参数
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.dao.userDao">
<!-- 查询单个用户 -->
<select id="findStudentIds" parameterType="java.lang.Integer" resultType="com.bean.user">
SELECT * FROM user WHERE id = #{id}
</select>
</mapper>
<mappers>
<mapper resource="mappers/order.xml"></mapper>
<mapper resource="mappers/user.xml"></mapper>
</mappers>
这里一定需要注意在配置文件之中需要两个映射文件都需要加载并且在同一个mappers标签之下。我在这个错误浪费了好多的时间,还是自己不细心。
图中拿到user_id三天记录两个1一个10分成两次去数据库查找实现了懒加载。
注解
直接装载在方法上面
优点:比较简单
缺点:SQL语句的改变就需要重新编译
注解 作用
>标签 | 作用 |
---|---|
@Intsert | 实现新增 |
@Update | 实现更新 |
@Delete | 实现删除 |
@Select | 实现查询 |
@Results | 实现结果集封装 |
@ResultMap | 实现引用 @Results 定义的封装 |
@One | 实现一对一结果集封装 |
@Many | 实现一对多结果集封装 |
select
public interface StudentMapper2 {
@Select("select * from Student")
public Student getStudentBySID();
}
update
@update("update student set Sname=#{name} where SID=#{SID}")
public void updateStudent(@Param("name") String Sname,@Param("SID") int SID)
insert
@Insert("insert into Student(SID,Sname,Sage,Ssex) values(#{SID},#{name},#{Sage},#{Ssex})")
public int insertStudent(Student student);
delete
@Delete("delete form student where SID={SID}")
public void deleteStudent(int SID);
一对一映射
@Results(id = "result",value = {
@Result(column = "SID",property = "SID"),
@Result(column = "Sname",property = "name"),
@Result(column = "Sage",property = "Sage"),
@Result(column = "Ssex",property = "Ssex"),
@Result(column = "score",property = "SID",one = @One(select = "com.dao.studentDao.StudentScore",fetchType = FetchType.EAGER)
})
需要注意的是one表示的是一对一,many表示一对多是使用,fetchtype加载类型,立即加载为EAGER
以上是我对mybatis的学习如果有错误的地方欢迎大佬指正