一、导包+配置文件+pojo类
1、jar包:mybatis的核心包和依赖包+连接数据库的jar包
2、日志文件(可以不需要)
3、SqlMapConfig.xml配置
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--给trd.mybatis.pojo包下的所有类取别名(为简单类名且首字母大小写不敏感) -->
<typeAliases>
<package name="trd.mybatis.pojo"/>
</typeAliases>
<!-- 和spring整合后 environments配置将废除 -->
<environments default="development">
<environment id="development">
<!-- 使用jdbc事务管理 -->
<transactionManager type="JDBC" />
<!-- 数据库连接池 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/mybatis" />
<property name="username" value="root" />
<property name="password" value="a123" />
</dataSource>
</environment>
</environments>
<!-- 加载trd.mybatis.mapper包下的所有映射文件(映射文件名有限制) -->
<mappers>
<package name="trd.mybatis.mapper"/>
</mappers>
</configuration>
4、pojo类
// 用户pojo类,对应用户表
package trd.mybatis.pojo;
import java.util.Date;
import java.util.List;
public class User {
private int id;
private String username;
private Date birthday;
private String sex;
private String address;
// 一个用户能有多个订单
private List<Orders> orderList;
}
//=============================================================================
// 订单pojo类,对应订单表
package trd.mybatis.pojo;
import java.util.Date;
public class Orders {
// oid和uid没有和Orders表的对应列的名字一样,是为了测试(resultMap)手动映射
private int oid; // id
private int uid; // user_id
private String number;
private Date createtime;
private String note;
// 一个订单归属于一个用户
private User user;
}
//============================================================================
// 复杂pojo类,嵌套了其他pojo
package trd.mybatis.pojo;
import java.util.Arrays;
import java.util.List;
public class UserWrapper {
private User user;
// 测试foreach遍历
private int[] intArr;
private List<Integer> integerList;
}
二、结果映射(resultMap)
- 作用:pojo类属性名和数据库中查询结果名不同时,用resultMap来手动映射。
- 注意:当resultMap只映射简单pojo类时(也就是此时pojo类不存在嵌套其他pojo或者不存在集合),resultMap里可以只写出不同名的属性,其余同名的属性会自动进行映射
<!--
type:映射到哪一个pojo
id:为该resultMap的唯一id,用来被需要用到它的地方所引用
-->
<resultMap type="Orders" id="mapOrder">
<!--
id标签:定义主键 ,非常重要。如果是多个字段,则定义多个id
result标签:定义普通属性
————column属性:数据库中的列名(查询出的结果)
————property属性:对应pojo中的属性名
-->
<id column="id" property="oid"/>
<result column="user_id" property="uid"/>
</resultMap>
<select id="findAllInOrders" resultMap="mapOrder">
SELECT * FROM orders
</select>
三、动态sql
(只测试了常用的where,if,foreach。而choose, when, otherwise类似java中的switch,when对应case,otherwise对应default,且用的相对少,就没有测试)
1、where+if
(1)where标签:有sql子句的情况下才会插入where。而且,若整个sql语句的开头为 and 或者是 or ,where 元素也会将它们去除
(2)if标签:test属性值是判断的条件
<!-- 抽取出重复的sql片段,使用include标签引用它,可以达到重用的目的 -->
<sql id="selectSql">
select * from user
</sql>
<!--===================================================================================-->
<select id="findUserByCriteria" parameterType="User" resultType="User">
<include refid="selectSql"/>
<where>
<if test="id != null and id != '' ">
and id = #{id}
</if>
<if test="username != null and username != '' ">
and username = #{username}
</if>
</where>
</select>
2、foreach(遍历标签,构建IN条件语句时用的多)
属性介绍:
- collection:可迭代的对象。可以直接是数组,集合(此时collection属性值就是array和list),也可以是包装在pojo类中的数组和集合(这时用包装类对应的的引用属性)
- item:本次迭代获取的元素
- open:在前面添加的sql片段
- close:在结尾处添加的sql片段
- separator:指定遍历的元素之间使用的分隔符
<select id="findUserById" resultType="User" parameterType="UserWrapper">
<include refid="selectSql"/>
<where>
<!-- 参数为封装在pojo类中的集合 -->
<!-- <foreach collection="integerList" item="id" open=" id IN(" separator="," close=")">
#{id}
</foreach> -->
<!-- 参数为集合 -->
<!-- <foreach collection="list" item="id" open=" id IN(" separator="," close=")">
#{id}
</foreach> -->
<!-- 参数为数组 -->
<foreach collection="array" item="id" open=" id IN(" separator="," close=")">
#{id}
</foreach>
</where>
</select>
四、关联查询
1、原始的DBUtils解决多表关联查询:
将多表查询的结果用MapListHandler(一行对应一个map(键为列名),许多map又被封装进一个list集合中)封装起来,遍历这个list集合,在利用beanUtils工具将每个map封装为简单的javabean(多个),再将这些javabean进行对应的嵌套。
2、MyBatis解决多表关联查询(用resultMap):
(1)一对一:一个pojo里面嵌套了另一个pojo
(1.1) association标签:关联一个复杂类型(比如pojo)
属性介绍:
- javaType:指定关联的这个复杂类型的java类型
- property:pojo中对应的属性名
(1.2) mapper的配置
<!-- ==================一对一查询,订单表对应用户表(订单表为中心)============== -->
<resultMap type="Orders" id="order">
<id column="orders_id" property="oid"/>
<result column="note" property="note"/>
<result column="number" property="number"/>
<result column="createtime" property="createtime"/>
<association property="user" javaType="trd.mybatis.pojo.User">
<id column="user_id" property="id"/>
<result column="username" property="username"/>
<result column="address" property="address"/>
</association>
</resultMap>
<select id="findOrdersInMultilist" resultMap="order">
SELECT
u.username,
u.address,
o.user_id,
o.id AS orders_id,
o.number,
o.createtime,
o.note
FROM `user` u RIGHT JOIN orders o
ON u.id=o.user_id
</select>
(1.3) 数据库的查询结果
![1da2ee08f552596d813aaebba5116209.png](https://img-blog.csdnimg.cn/img_convert/1da2ee08f552596d813aaebba5116209.png)
(2)一对多:一个pojo里面嵌套了集合的pojo
(2.1)collection标签:关联一个复杂类型的集合
属性介绍:
- ofType:这个复杂类型集合里装的对象的具体类型
- property:pojo中对应的属性名
(2.2) mapper的配置
<!-- ================== 一对多查询,用户表对应订单表(用户表为中心) ============= -->
<resultMap type="user" id="user">
<id column="user_id" property="id"/>
<result column="username" property="username"/>
<result column="address" property="address"/>
<!-- 属性说明(其余的和上面一样):
ofType:集合装的对象的具体类型
-->
<collection property="orderList" ofType="orders">
<id column="orders_id" property="oid"/>
<result column="note" property="note"/>
</collection>
</resultMap>
<select id="findUserInMultilist" resultMap="user">
SELECT
u.username,
o.id AS orders_id,
o.user_id,
o.number,
o.createtime,
o.note,
u.address
FROM `user` u LEFT JOIN orders o
ON u.id=o.user_id
</select>
(2.3) 数据库的查询结果
![279549141b6f79876a48f26b3fae3b04.png](https://img-blog.csdnimg.cn/img_convert/279549141b6f79876a48f26b3fae3b04.png)
(3)注意:
存在pojo嵌套时,数据库中查出来的列的名字和pojo中属性名相同时,也不能省略。
五、Mapper接口+测试类
1、映射文件对应的接口
package trd.mybatis.mapper;
import java.util.List;
import trd.mybatis.pojo.Orders;
import trd.mybatis.pojo.User;
import trd.mybatis.pojo.UserWrapper;
public interface UserMapper {
// 测试resultMap
List<Orders> findAllInOrders();
// 动态sql语句值if
User findUserByCriteria(User user);
// 动态sql之foreach
List<User> findUserById(int[] intArr);
List<User> findUserById(UserWrapper wrapper);
List<User> findUserById(List<Integer> integerList);
// 多表查询
List<Orders> findOrdersInMultilist();
List<User> findUserInMultilist();
}
2、测试类
package trd.mybatis.test;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test;
import trd.mybatis.mapper.UserMapper;
import trd.mybatis.pojo.Orders;
import trd.mybatis.pojo.User;
import trd.mybatis.pojo.UserWrapper;
public class Test1 {
private InputStream is = null;
private SqlSessionFactoryBuilder builder = null;
private SqlSessionFactory factory = null;
private SqlSession sqlSession = null;
// 每次junit测试前调用,来给私有属性赋值
@Before
public void before() throws IOException{
is = Resources.getResourceAsStream("sqlMapConfig.xml");
builder = new SqlSessionFactoryBuilder();
factory = builder.build(is);
sqlSession = factory.openSession();
}
// 测试查询所有订单(用resultMap手动映射)
@Test
public void findAllInOrders() throws IOException{
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<Orders> ordersList = mapper.findAllInOrders();
for (Orders orders : ordersList) {
System.out.println(orders);
}
}
// 测试动态sql的if标签
@Test
public void findUserByCriteria() throws IOException{
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = new User();
// user.setId(1);
user.setUsername("小强");
User user2 = mapper.findUserByCriteria(user);
System.out.println(user2);
}
// 测试动态sql的foreach标签(参数为其他pojo类)
@Test
public void findUserById1() throws IOException{
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
UserWrapper wrapper = new UserWrapper();
List<Integer> integerList = new ArrayList<Integer>();
integerList.add(1);
integerList.add(10);
integerList.add(25);
wrapper.setIntegerList(integerList);
List<User> userList = mapper.findUserById(wrapper);
for (User user : userList) {
System.out.println(user);
}
}
// 测试动态sql的foreach标签(参数为List集合)
@Test
public void findUserById2() throws IOException{
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<Integer> integerList = new ArrayList<Integer>();
integerList.add(1);
integerList.add(10);
integerList.add(25);
List<User> userList = mapper.findUserById(integerList);
for (User user : userList) {
System.out.println(user);
}
}
// 测试动态sql的foreach标签(参数为数组)
@Test
public void findUserById3() throws IOException{
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
int[] intArr = new int[]{1,10,25,6595,5};
List<User> userList = mapper.findUserById(intArr);
for (User user : userList) {
System.out.println(user);
}
}
// 测试多表查询中的一对一查询(一份订单只能对应一个用户)
@Test
public void findOrdersInMultilist() throws IOException{
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<Orders> ordersList = mapper.findOrdersInMultilist();
for (Orders orders : ordersList) {
System.out.println(orders);
}
}
// 测试多表查询中的一对多查询(一个用户对应多份订单)
@Test
public void findUserInMultilist() throws IOException{
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> userList = mapper.findUserInMultilist();
for (User user : userList) {
System.out.println(user);
}
}
}