一、MyBatis入门
1.概念
MyBatis 是一个开源、轻量级的数据持久化框架,是 JDBC 和 Hibernate 的替代方案。MyBatis 内部封装了 JDBC,简化了加载驱动、创建连接、创建 statement 等繁杂的过程,开发者只需要关注 SQL 语句本身
2.特点
MyBatis是免费且开源的。与 JDBC 相比,减少了 50% 以上的代码量。MyBatis是最简单的持久化框架,体积小巧并且学习门槛低。MyBatis相当灵活,不会对应用程序或者数据库的现有设计强加任何影响,SQL 写在 XML 中,和程序逻辑代码分离,降低耦合度,便于同一管理和优化,提高了代码的可重用性。提供 XML 标签,支持编写动态 SQL语句。提供映射标签,支持实体对象与数据库的表字段关系映射。
二、MyBatis开发中遇到的问题
问题一:映射器没有加载至主配置文件
解决:
把映射器加载至主配置文件
启发:
遇到映射文件没有在映射器注册类,可能是没有在主配置文件中加载配置文件
问题二:以映射器接口的方式加载映射器时,接口名和映射文件名不一致导致的异常
解决:
将接口名和映射文件名保持一致
问题三:遇到数据库中的字段名和参数不一致的情况
解决办法:
目录
问题二:以映射器接口的方式加载映射器时,接口名和映射文件名不一致导致的异常
参数问题
-
只有一个参数时,不考虑参数的名称
select * from earthquake where cankaoweizhi like concat('%', #{keyword}, '%');
2. 当有多个参数时,要考虑参数的传入问题
-
第一种方式:通过默认的参数名称传入参数
-
第二种方式:通过传入一个map集合
select * from earthquake where jingdu between #{jingdu1} and #{jingdu2} and weidu between #{weidu1} and #{weidu2}
第三种方式:通过注解的形式传入参数
// 查询条件中有多个参数时,通过@param注解的形式传入参数 public List<Earthquake> SelectEarthquakeListByParam(@Param("jingduMin") double jingdu1,@Param("jingduMax") double jingdu2, @Param("weiduMin")double weidu1, @Param("weiduMax") double weidu2);
<!-- 当有多个参数时,通过注解参数的传入问题--> <!-- --> <select id="SelectEarthquakeListByParam" resultType="com.my.entity.Earthquake"> select * from earthquake where jingdu between #{jingduMin} and #{jingduMax} and weidu between #{weiduMin} and #{weiduMax} </select>
-
使用自定义JavaBean封装多个传入参数
-
resultType:设置查询结果的封装类型
-
parameterType:设置传入参数的封装类型(在我们使用的高版本的mybatis中不用设置该参数,在老版本中要设置该参数)
select * from earthquake where jingdu between #{conditionjingduMin} and #{conditionjingduMax} and weidu between #{conditionweiduMin} and #{conditionweiduMax}
问题四:遇到添加操作需要返回主键的情况
解决:
问题五:多表连接时,遇到一对多的情况
SELECT * FROM employee_info AS emp INNER JOIN department_info AS dep ON emp.dept_id = dep.dept_id WHERE dep.dept_name in #{deptName}
<select id="selectEmployeeListInDeptNames"
resultMap="EmployeeResultMap">
SELECT *
FROM employee_info AS emp
INNER JOIN department_info AS dep ON
emp.dept_id = dep.dept_id
WHERE dep.dept_name in
<foreach collection="deptList" item="deptName" separator=","
open="(" close=")">
#{deptName}
</foreach>
</select>
<select id="selectWebsiteListLikeName"
resultMap="EmployeeResultMap">
SELECT *
FROM employee_info AS emp
INNER
JOIN department_info
AS dep ON emp.dept_id = dep.dept_id
WHERE
emp.emp_name LIKE concat('%',
#{name}, '%')
order by emp_id ${orderMode}
</select>
解决:首先,我们要创建两张表对应的两个实体类,使用resultMap属性,在resultMap中将字段名和实体属性对应起来。
启发
1.多步查询
-
当遇到两个表的查询,一个实体类中包含另外一个实体类的情况应采用这种方式解决
-
在主表的一个字段为另外一个实体时,
-
结果类型设置成resultMap
-
在resultMap中设置字段、属性对应关系时,将最后一个字段对应的自定义类属性值用<association> 标记结局即可,其中包含了该字段在另一张表的查询连接条件、对应的属性值的类型javaType
<resultMap type="com.my.entity.Student" id="studentResultMap">
<id column="id" property="id" />
<result column="name" property="name" />
<result column="sex" property="sex" />
<!-- 一对一的映射,(一个实体类中有另一个实体,多表查询) -->
<association column="cardId" property="stuCard"
javaType="com.my.entity.StudentCard"
select="com.my.mapper.StudentCardMapper.selectStudentCardById" />
</resultMap>
<select id="selectStudentById" resultMap="studentResultMap">
select * from Student
where id = #{id}
</select>
一对多
1. 分步查询
<resultMap type="com.my.entity.User" id="userResultMap1">
<id column="id" property="id"/>
<result column="name" property="name"/>
<result column="pwd" property="pwd"/>
<!-- 最后一个属性是一个list集合,类型是order-->
<collection property="orderList"
column="id"
ofType="com.my.entity.Order"
select="com.my.mapper.OrderMapper.selectOrderById"
/>
</resultMap>
-
懒加载(建立在分布查询)
<!-- fetchType="lazy" 懒加载,只有在用该sql语句的时候才加载,不用不加载--> <collection property="orderList" column="id" ofType="com.my.entity.Order" select="com.my.mapper.OrderMapper.selectOrderById" fetchType="lazy"/>
2.单步查询
### 一对多
#### 1.分步查询
```html
<resultMap type="com.my.entity.User" id="userResultMap1">
<id column="id" property="id"/>
<result column="name" property="name"/>
<result column="pwd" property="pwd"/>
<!-- 最后一个属性是一个list集合,类型是order-->
<collection property="orderList"
column="id"
ofType="com.my.entity.Order"
select="com.my.mapper.OrderMapper.selectOrderById"
/>
</resultMap>
```
2. 懒加载(建立在分布查询)
> <!-- fetchType="lazy" 懒加载,只有在用该sql语句的时候才加载,不用不加载-->
> <collection property="orderList" column="id"
> ofType="com.my.entity.Order"
> select="com.my.mapper.OrderMapper.selectOrderById"
> fetchType="lazy"/>
#### 2.单步查询
```html
<!-- 单步查询 -->
<resultMap type="com.my.entity.User" id="userResultMap2">
<id column="id" property="id" />
<result column="name" property="name" />
<result column="pwd" property="pwd" />
<!-- 最后一个属性是一个list集合,类型是order 两个参数-->
<collection property="orderList" ofType="com.my.entity.Order">
<id column="orderid" property="orderid"/>
<result column="ordernum" property="ordernum"/>
</collection>
</resultMap>
<select id="selectUserOrderById2" resultMap="userResultMap2">
SELECT * FROM user
INNER JOIN order_info ON user.id = order_info.userId
where id = #{id};
</select>
```