Hibernate:是一个ORM框架,不需要手动配置sql语句,数据库无关性好。
MyBatis:不完全是一个ORM框架,需要手动配置sql语句,数据库无关性不好。
SqlMapConfig.xml:核心配置文件。
Mapper.xml:用于配置sql语句,该文件需要通过mapper标签在核心配置文件中加载。
SqlSessionFactory:会话工厂对象,用于产生对应的SqlSession对象。
SqlSession:可以通过该对象执行操作数据库的sql语句或者获得Mapper接口的动态代理对象,该对象使用完后需释放,若是修改数据库的语句,需要通过该对象的commit()方法提交事务。
Executor:Mybatis底层的执行器接口,用于操作数据库,他又两个实现类,一个是基本执行器、一个是缓存执行器。
MappedStatement:Mybatis底层的一个语句封装类。在mapper.xml中,一个sql语句与一个MappedStatement对象对应。同时,该类对sql输入参数和输出结果都进行了定义。
其它类:
SqlSessionFactoryBuilder:用于读取SqlMapConfig.xml,并创建SqlSessionFactory。
基本的开发思路:
1.编写Mapper接口用于确定操作数据库的方法。
2.编写与该Mapper接口对应的Mapper.xml文件,使用Mybatis开发规范完成编写。
3.在SqlMapConfig.xml文件中加入Mapper.xml文件。
4.测试:使用sqlSession的getMapper()方法,获得对应Mapper接口的动态代理对象,调用该对象的方法完成数据库的操作。
共四点:
1.Mapper.xml文件中的namespace与mapper接口的类路径相同。
2.Mapper.xml文件中每个statement的id与Mapper接口中定义的方法名相同。
3.Mapper.xml文件中每个statement的parameterType的类型与Mapper接口的参数类型相同。
4.Mapper.xml文件中每个statement的resultType的类型与Mapper接口的返回值类型相同。
SqlMapConfig.xml中配置的内容和顺序如下:
properties(属性):用于加载外部配置文件
settings(全局配置参数)
typeAliases(类型别名):用于为类定义别名,可以单个定义或者批量定义.
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境集合属性对象)
environment(环境子属性对象)
transactionManager(事务管理)
dataSource(数据源)
mappers(映射器):加载Mapper.xml文件 。可以单个加载或批量加载。
1.#{}:使用JDBC中的PreparedStatement完成sql语句的预编译,#{}表示一个占位符。可以接受简单数据类型和POJO属性值。
2${}:表示拼接sql串,可以接收简单数据类型哦POJO属性值(接受的简单数据类型之${}中只能是value)。
输入映射的类型可以是简单类型、POJO类型,还有POJO包装对象(即POJO类中的一个属性是另外一个POJO)
。如果一个sql输入参数有多个或者需要一个LIST或者数组,可以用一个POJO类封装输入参数。在Mapper.xml中引入该POJO类完成传参。
POJO包装对象的配置如下
public class QueryVo {
// 包含其他的pojo
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
Mapper.xml的配置可以参考
<!-- 根据用户名模糊查询 -->
<select id="findUserByQueryVo" parameterType="pojo.QueryVo"
resultType="pojo.User">
select *
from user
<!-- 方式一 -->
where username like '%${user.username}%'
<!-- 方式二 -->
<!-- where username like "%"#{user.username}"%" -->
</select>
输出映射可以是简单类型,POJO类型或者POJO列表。
<!-- 根据用户名模糊查询 -->
<select id="findUserByQueryVo" parameterType="pojo.QueryVo"
resultType="pojo.User">
select *
from user
<!-- 方式一 -->
where username like '%${user.username}%'
<!-- 方式二 -->
<!-- where username like "%"#{user.username}"%" -->
</select>
如果查询结果中的列名与POJO对象的属性名都一一对应,则使用resultType自动获取查询结果即可,否则需要使用resultMap完成查询结果的映射。resultMap还可以用于一对一及一对多的关联映射。
<!-- resultMap最终还是要将结果映射到pojo上,type就是指定映射到哪一个pojo -->
<!-- id:设置ResultMap的id -->
<resultMap type="order" id="orderResultMap">
<!-- 定义主键 ,非常重要。如果是多个字段,则定义多个id -->
<!-- property:主键在pojo中的属性名 -->
<!-- column:主键在数据库中的列名 -->
<id property="id" column="id" />
<!-- 定义普通属性 -->
<result property="userId" column="user_id" />
<result property="number" column="number" />
<result property="createtime" column="createtime" />
<result property="note" column="note" />
</resultMap>
<!-- 查询所有的订单数据 -->
<select id="queryOrderAll" resultMap="orderResultMap">
SELECT id, user_id,
number,
createtime, note FROM `order`
</select>
由下图可见,user实体对于order实体是1对多的映射,order实体对于user实体是一对一的映射。
需求:现在需要查询每一个订单及其用户信息。则需要映射的结果包括order表和user表的结果。
POJO配置
public class Order {
// 订单id
private int id;
// 用户id
private Integer userId;
// 订单号
private String number;
// 订单创建时间
private Date createtime;
// 备注
private String note;
//用户属性
private User user;
...
}
Mapper.xml配置
使用resultMap标签完成结果映射
<resultMap type="order" id="OrderUserResultMap">
<id property="id" column="id" />
<result property="userId" column="user_id" />
<result property="number" column="number" />
<result property="createtime" column="createtime" />
<result property="note" column="note" />
<!-- association:配置一对一属性 -->
<!-- property:order里面的User属性名 -->
<!-- javaType:属性类型 -->
<association property="user" javaType="user">
<!-- id:声明逐渐,表示user_id是关联查询对象的唯一标识 -->
<id property="id" column="user_id" />
<result property="username" column="username" />
<result property="address" column="address" />
</association>
</resultMap>
<select id="queryOrderUserResultMap" resultMap="OrderUserResultMap">
select o.*,
u.username,
u.address
from orders o left join user u
on o.user_id = u.id
</select>
需求:现在需要查询每一个用户及其订单信息。则需要映射的结果包括order表和user表的结果。
POJO配置
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private Integer id;
private String username;// 用户姓名
private String sex;// 性别
private Date birthday;// 生日
private String address;// 地址
private List<Order> orders;
....
}
Mapper.xml配置
<!-- 一对多查询 -->
<resultMap type="user" id="userOrderResultMap">
<id property="id" column="id" />
<result property="username" column="username" />
<result property="birthday" column="birthday" />
<result property="sex" column="sex" />
<result property="address" column="address" />
<!-- 配置一对多的关系 -->
<collection property="orders" javaType="list" ofType="order">
<!-- 配置主键,是关联Order的唯一标识 -->
<result property="number" column="number" />
<result property="createtime" column="createtime" />
<result property="note" column="note" />
</collection>
</resultMap>
<!-- 一对多关联,查询订单同时查询该用户下的订单 -->
<select id="queryUserOrder" resultMap="userOrderResultMap">
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>
通过if、where、sql片段和foreach标签可以产生动态的sql语句。
可以根据test属性的返回值,输出标签体中的sql语句
<!-- 根据条件查询用户 -->
<select id="queryUserByWhere" parameterType="user" resultType="user">
SELECT id, username, birthday, sex, address FROM `user`
WHERE 1=1
<if test="sex != null and sex != ''">
AND sex = #{sex}
</if>
<if test="username != null and username != ''">
AND username LIKE
'%${username}%'
</if>
</select>
<!-- 根据条件查询用户 -->
<select id="queryUserByWhere" parameterType="user" resultType="user">
SELECT id, username, birthday, sex, address FROM `user`
<!-- where标签可以自动添加where,同时处理sql语句中第一个and关键字 -->
<where>
<if test="sex != null">
AND sex = #{sex}
</if>
<if test="username != null and username != ''">
AND username LIKE '%${username}%'
</if>
</where>
</select>
可以将经常使用的算sql用sql标签保存,通过标签加载,实现sql片段的代码重用。
<!-- 声明sql片段 -->
<sql id="userFields">
id, username, birthday, sex, address
</sql>
<!-- 根据条件查询用户 -->
<select id="queryUserByWhere" parameterType="user" resultType="user">
<!-- SELECT id, username, birthday, sex, address FROM `user` -->
<!-- 使用include标签加载sql片段;refid是sql片段id -->
SELECT <include refid="userFields" /> FROM `user`
<!-- where标签可以自动添加where关键字,同时处理sql语句中第一个and关键字 -->
<where>
<if test="sex != null">
AND sex = #{sex}
</if>
<if test="username != null and username != ''">
AND username LIKE
'%${username}%'
</if>
</where>
</select>
需求:需要查询输入多个POJO参数时,可以使用foreach标签来传递数组或者List。
如:SELECT * FROM user WHERE id IN (1,10,24)
public class QueryVo implements Serializable{
private static final long serialVersionUID = 1L;
private List<Integer> ids;
...
}
<!-- 根据ids查询用户 -->
<select id="queryUserByIds" parameterType="queryVo" resultType="user">
SELECT * FROM `user`
<where>
<!-- foreach标签,进行遍历 -->
<!-- collection:遍历的集合,这里是QueryVo的ids属性 -->
<!-- item:遍历的项目,可以随便写,,但是和后面的#{}里面要一致 -->
<!-- open:在前面添加的sql片段 -->
<!-- close:在结尾处添加的sql片段 -->
<!-- separator:指定遍历的元素之间使用的分隔符 -->
<foreach collection="ids" item="item" open="id IN (" close=")" separator=",">
#{item}
</foreach>
</where>
</select>
《黑马课程的培训资料》