1.mybatis核心文件和概念说明
1.配置文件
a)整合spring之后,配置了mybatis的运行环境等信息,此文件作为mybatis的全局配置文件。
b) Mapper.xml,此文件作为mybatis的sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在SqlMapConfig.xml中加载。
2.SqlSessionFactory
通过mybatis环境等配置信息构造SqlSessionFactory,即会话工厂,生命周期:sqlsessionFactory:全局范围(应用级别)。
3.sqlSession
通过会话工厂创建sqlSession即会话,通过sqlsession会话接口对数据库进行增删改查操作,生命周期:sqlsession:方法级别。
4.Executor执行器
mybatis底层自定义了Executor执行器接口来具体操作数据库,Executor接口有两个实现,一个是基本执行器(默认)、一个是缓存执行器,sqlsession底层是通过executor接口操作数据库的。
5.Mapped Statement
mybatis的底层封装对象,它包装了mybatis配置信息及sql映射信息等。mapper.xml文件中一个select\insert\update\delete标签对应一个Mapped Statement对象,select\insert\update\delete标签的id即是Mapped statement的id。
a)Mapped Statement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql前将输入的java对象映射至sql中,输入参数映射就是jdbc编程中对preparedStatement设置参数。
b)Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql后将输出结果映射至java对象中,输出结果映射过程相当于jdbc编程中对结果的解析处理过程。
2. XML开发方式
使用mybatis开发DAO层代码,只需要开发Mapper接口(dao接口)和Mapper约束文件,不需要编写实现类。
Mapper接口开发需要遵循以下规范:
1、 Mapper接口的类路径与Mapper.xml文件中的namespace相同。
2、 Mapper接口方法名称和Mapper.xml中定义的每个statement的id相同。
3、 Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同。
4、 Mapper接口方法的返回值类型和mapper.xml中定义的每个sql的resultType的类型相同。
代码如下:
mapper映射文件
<mapper namespace="mybatis.mapper.UserMapper">
<!-- 根据id获取用户信息 -->
<select id="findUserById" parameterType="int" resultType="mybatis.po.User">
select * from user where id = #{id}
</select>
</mapper>
mapper接口
public interface UserMapper {
//根据用户id查询用户信息
public User findUserById(int id) ;
}
<!-- 加载映射文件 -->
<mappers>
<mapper resource="mapper/UserMapper.xml"/>
</mappers>
注意:在项目集成spring时,直接在spring的配置中配置即可
3.查询简单用法
a)parameterType:定义输入到sql中的映射类型,可以映射的输入参数类型有:
简单类型、POJO类型、Map类型、List类型(数组)。
b)resultType:属性可以映射的java类型有:简单类型、POJO类型、Map类型。使用resultType进行输出映射时,要求sql语句中查询的列名和要映射的pojo的属性名一致。
代码示例:
接口:
public interface UserMapper {
public User findUserById(int id);
public List<User> findUserList(Object object);
}
mapper.xml
<!-- 简单查询 -->
<select id="findUserById" parameterType="int" resultType="User">
select * from user where id = #{id}
</select>
<!-- 使用包装类型查询用户,使用ognl从对象中取属性值,如果是包装对象可以使用 . 操作符来取内容部的属性,
user.username为ognl表达式用法-->
<select id="findUserList" parameterType="Object" resultType="user">
SELECT * FROM user where username like '%${user.username}%'
</select>
c)resultMap:若sql查询列名和pojo的属性名不一致,可以通过resultMap将列名和属性名作一个对应关系,最终将查询结果映射到指定的pojo对象中。实际上:resultType底层也是通过resultMap完成映射的。属性标签说明:
id标签:此属性表示查询结果集的唯一标识。如果是多个字段为复合唯一约束则定义多个。
Property:表示User类的属性。
Column:表示sql查询出来的字段名。
Column和property放在一块儿表示将sql查询出来的字段映射到指定的pojo类属性上。
result:普通结果,即pojo的属性。
代码示例:
接口:
public List<User> findUserListResultMap()
Mapper映射文件
<!-- 定义resultMap:将查询的列名和映射的pojo的属性名做一个对应关系 -->
<!-- type:指定查询结果要映射的pojo的类型,id:指定resultMap的唯一标示 -->
<resultMap type="user" id="userListResultMap">
<!--
id标签:映射查询结果的唯一列(主键列)
column:查询sql的列名
property:映射结果的属性名
-->
<id column="id_" property="c_id"/>
<!-- result标签:映射查询结果的普通列 -->
<result column="username" property="c_username"/>
</resultMap>
<!-- resultMap入门 -->
<select id="findUserListResultMap" resultMap="userListResultMap">
SELECT c_id id,c_username username FROM user
</select>
d)一对一查询
1、使用resultType进行结果映射,查询的列名和映射pojo的属性名称要一致。
创建包含两个表属性的pojo,做为查询结果的返回集resultType
<!-- 查询用户订单信息,需要用户和定订单两张表 -->
<select id="findOrdersList" resultType="mybatis.po.OrdersExt">
SELECT
orders.*,
user.username,
user.address
FROM
orders, user
WHERE orders.user_id = user.id
</select>
e)一对多查询
在一对多关联查询时,只能使用resultMap进行结果映射。
1、一对多关联查询时,sql查询结果有多条,而映射对象是一个。
2、resultType完成结果映射的方式的一条记录映射一个对象。
3、resultMap完成结果映射的方式是以[主信息]为主对象,[从信息]映射为集合或者对象,然后封装到主对象中。
标签说明:
Collection标签:定义了一对多关联的结果映射。
property=“orders”:关联查询的结果集存储在User对象的上哪个属性。
ofType=“orders”:指定关联查询的结果集中的对象类型即List中的对象类型。此处可以使用别名,也可以使用全限定名。
代码示例:
一个人的多个订单信息,封装查询返回的对象:
public class User{
private String id;
private String username;
private List<Order> orders;
}
在UserMapper.xml文件中,添加以下代码:
<resultMap type="user" id="userAndOrderRstMap">
<!-- 用户信息映射 -->
<id property="id" column="id"/>
<result property="username" column="username"/>
<!-- 一对多关联映射 -->
<collection property="orders" ofType="orders">
<id property="id" column="oid"/>
<result property="userId" column="id"/>
<result property="number" column="number"/>
<result property="createtime" column="createtime"/>
<result property="note" column="note"/>
</collection>
</resultMap>
<select id="findUserAndOrderRstMap" resultMap="userAndOrderRstMap">
SELECT
u.*,
o.id oid,
o.number,
o.createtime,
o.note
FROM
`user` u
LEFT JOIN orders o ON u.id = o.user_id
</select>
f)#{}和${}区别
区别1
#{} :相当于JDBC SQL语句中的占位符? (PreparedStatement),如:#{id}表示使用preparedstatement设置占位符号,并将输入变量id传到sql
${} : 相当于JDBC SQL语句中的连接符合 + (Statement),相当于JDBC中的 ?占位符
区别2
#{} : 进行输入映射的时候,会对参数进行类型解析(如果是String类型,那么SQL语句会自动加上’’)
${} :进行输入映射的时候,将参数原样输出到SQL语句中
区别3
#{} : 如果进行简单类型(String、Date、8种基本类型的包装类)的输入映射时,#{}中参数名称可以任意
${} : 如果进行简单类型(String、Date、8种基本类型的包装类)的输入映射时,${}中参数名称必须是value
区别4
底层解析方法不一样
#{}:是通过反射获取数据的---StaticSqlSource
${}:是通过OGNL表达式会随着对象的嵌套而相应的发生层级变化 --DynamicSqlSource
注意:${} :存在SQL注入问题 ,使用OR 1=1 关键字将查询条件忽略
4.插入的简单用法
插入数据之后,返回主键,添加selectKey标签实现主键返回。
- keyProperty:指定返回的主键,存储在pojo中的哪个属性
- order:selectKey标签中的sql的执行顺序,是相对与insert语句来说。由于mysql的自增原理,执行完insert语句之后才将主键生成,所以这里selectKey的执行顺序为after。
- resultType:返回的主键对应的JAVA类型
- LAST_INSERT_ID():是mysql的函数,返回auto_increment自增列新记录id值。
代码示例:
<insert id="insertUser" parameterType="mybatis.po.User">
<!-- selectKey将主键返回,需要再返回 -->
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
select LAST_INSERT_ID()
</selectKey>
insert into user(username,birthday,sex,address)
values(#{username},#{birthday},#{sex},#{address});
</insert>
5.删除用法
<!-- 删除用户 -->
<delete id="deleteUserById" parameterType="int">
delete from user where id=#{id}
</delete>
6.修改用法
<!-- 更新用户 -->
<update id="updateUser" parameterType="mybatis.po.User">
update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address}
where id=#{id}
</update>
7.动态SQL
- if标签使用方法
代码示例:
<select id="findUserList" parameterType="queryVo" resultType="user">
SELECT * FROM user where 1=1
<if test="user != null">
<if test="user.username != null and user.username != ''">
AND username like '%${user.username}%'
</if>
</if>
</select>
- where标签使用方法
在where语句后的sql中使用1=1,虽然可以保证sql语句的完整性:但是存在性能问题。
使用where标签可以解决此问题
代码示例:
<select id="findUserList" parameterType="queryVo" resultType="user">
SELECT * FROM user
<!-- where标签会处理它后面的第一个and -->
<where>
<if test="user != null">
<if test="user.username != null and user.username != ''">
AND username like '%${user.username}%'
</if>
</if>
</where>
</select>
- sql片段
将常用的不变的sql提取成公共的sql片段,在其他的sql需要使用时,直接引用即可。
代码示例:
<sql id="query_user_where">
<if test="user != null">
<if test="user.username != null and user.username != ''">
AND username like '%${user.username}%'
</if>
</if>
</sql>
<!-- 使用包装类型查询用户 使用ognl从对象中取属性值,如果是包装对象可以使用.操作符来取内容部的属性 -->
<select id="findUserList" parameterType="queryVo" resultType="user">
SELECT * FROM user
<!-- where标签会处理它后面的第一个and -->
<where>
<include refid="query_user_where"></include>
</where>
</select>
注意:
1、如果引用其它mapper.xml的sql片段,则在引用时需要加上namespace,如下:<include refid="namespace.sql片段”/>
- foreach标签的使用
代码示例:
<sql id="query_user_where">
<if test="user != null">
<if test="user.username != null and user.username != ''">
AND username like '%${user.username}%'
</if>
</if>
<if test="ids != null and ids.size() > 0">
<!-- collection:指定输入的集合参数的参数名称 -->
<!-- item:声明集合参数中的元素变量名 -->
<!-- open:集合遍历时,需要拼接到遍历sql语句的前面 -->
<!-- close:集合遍历时,需要拼接到遍历sql语句的后面 -->
<!-- separator:集合遍历时,需要拼接到遍历sql语句之间的分隔符号 -->
<foreach collection="ids" item="id" open=" AND id IN ( "
close=" ) " separator=",">
#{id}
</foreach>
</if>
</sql>
注意:如果parameterType不是POJO类型,而是List或者Array的话,那么foreach语句中,collection属性值需要固定写死为list或者array。
以上只是对Mybatis使用的简单总结
如有错误,敬请指正。