Mybatis基础系列(二)

一、输入映射和输出映射

1.1、parameterType(输入类型)

1.1.1、传递简单类型

使用#{}占位符,或者${}进行sql拼接。

1.1.2、传递pojo对象

参考Mybatis基础系列(一)
Mybatis使用ognl表达式解析对象字段的值,#{}或者${}括号中的值为pojo属性名称。

1.1.3、传递pojo包装对象

包装对象:Pojo类中的一个属性是另外一个pojo。
需求:根据用户名模糊查询用户信息,查询条件放到QueryVo的user属性中。
编写QueryVo:

public class QueryVo {
    // 包含其他的pojo
    private User user;
    public User getUser() {
        return user;
    }
    public void setUser(User user) {
        this.user = user;
    }
}

Mapper.xml文件:
在UserMapper.xml中配置sql:

<!-- 根据用户名模糊查询 -->
<select id="findUserByQueryVo" parameterType="QueryVo" resultType="com.long.pojo.User">
    select * from user where username like "%"#{user.username}"%"
</select>

Mapper接口:
在UserMapper接口中添加方法:

public interface UserMapper {
    //遵循四个原则
    //接口 方法名  == UserMapper.xml 中 id 名
    //返回值类型  与  UserMapper.xml文件中返回值类型要一致
    //方法的入参类型 与 UserMapper.xml中入参的类型要一致
    //命名空间 绑定此接口
    public List<User> findUserByQueryVo(QueryVo vo);
}

创建测试文件:

@Test
public void testQueryUserByQueryVo() {
    // mybatis和spring整合,整合之后,交给spring管理
    SqlSession sqlSession = this.sqlSessionFactory.openSession();
    // 创建Mapper接口的动态代理对象,整合之后,交给spring管理
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    // 使用userMapper执行查询,使用包装对象
    QueryVo queryVo = new QueryVo();
    // 设置user条件
    User user = new User();
    user.setUsername("张");
    // 设置到包装对象中
    queryVo.setUser(user);

    // 执行查询
    List<User> list = userMapper.queryUserByQueryVo(queryVo);
    for (User u : list) {
        System.out.println(u);
    }

    // mybatis和spring整合,整合之后,交给spring管理
    sqlSession.close();
}

1.2、resultType(输出类型)

1.2.1、输出简单类型

需求:查询用户表数据条数:
在UserMapper.xml中配置sql:

<select id="countUser" resultType="Integer">
        select count(1) from user
</select>

在UserMapper添加方法:

public interface UserMapper {
    //查询数据条数
    public Integer countUser();
}

测试:

@Test
public void testQueryUserCount() {
    // mybatis和spring整合,整合之后,交给spring管理
    SqlSession sqlSession = this.sqlSessionFactory.openSession();
    // 创建Mapper接口的动态代理对象,整合之后,交给spring管理
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

    // 使用userMapper执行查询用户数据条数
    int count = userMapper.queryUserCount();
    System.out.println(count);

    // mybatis和spring整合,整合之后,交给spring管理
    sqlSession.close();
}

1.2.2、输出pojo对象

输出pojo对象可以参考上篇博客。

1.2.3、输出resultMap对象

resultType可以指定将查询结果映射为pojo,但需要pojo的属性名和sql查询的列名一致方可映射成功。
如果sql查询字段名和pojo的属性名不一致,可以通过resultMap将字段名和属性名作一个对应关系 ,resultMap实质上还需要将查询结果映射到pojo对象中。
resultMap可以实现将查询结果映射为复杂类型的pojo,比如在查询结果映射对象中包括pojo和list实现一对一查询和一对多查询。
需求:查询订单表order的所有数据:
数据库如下:
这里写图片描述
Order对象:

public class Order {
    // 订单id
    private int id;
    // 用户id
    private Integer userId;  //名字和数据库字段不一样
    // 订单号
    private String number;
    // 订单创建时间
    private Date createtime;
    // 备注
    private String note;
    get/set。。。
}

创建OrderMapper.xml配置文件:

<resultMap type="Orders" id="orders">
    <result column="user_id" property="userId"/>
</resultMap>
<select id="selectOrdersList" resultMap="orders">
    <SELECT id, user_id, number, createtime, note FROM orders 
</select>

Mapper接口:

public interface OrderMapper {
    //  查询订单表order的所有数据
    public List<Orders> selectOrdersList();
}

测试程序:

//查询订单表order的所有数据
@Test
public void testOrderList() throws Exception {
    //加载核心配置文件
    String resource = "sqlMapConfig.xml";
    InputStream in = Resources.getResourceAsStream(resource);
    //创建SqlSessionFactory
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
    //创建SqlSession
    SqlSession sqlSession = sqlSessionFactory.openSession();

    OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);

    List<Orders> ordersList = mapper.selectOrdersList();
    for (Orders orders : ordersList) {
        System.out.println(orders);
    }
}

二、动态SQL

通过mybatis提供的各种标签方法实现动态拼接sql。

2.1、动态SQL之if标签

需求:根据性别和名字查询用户
UserMapper接口:

public interface UserMapper {
    //  根据性别和名字查询用户
    public List<User> selectUserBySexAndUsername(User user);
}

UserMapper.xml配置sql:

<!--    根据性别和名字查询用户  where 可以去掉第一个前ANd   -->
<select id="selectUserBySexAndUsername" parameterType="User" resultType="User">
    select * from user
    <where>
        <if test="sex != null and sex != ''">
             sex = #{sex} 
        </if>
        <if test="username != null and username != ''">
            and username = #{username}
        </if>
    </where>
</select>

测试:

//  根据性别和名字查询用户
@Test
public void testfindUserBySexAndUsername() throws Exception {
    //加载核心配置文件
    String resource = "sqlMapConfig.xml";
    InputStream in = Resources.getResourceAsStream(resource);
    //创建SqlSessionFactory
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
    //创建SqlSession
    SqlSession sqlSession = sqlSessionFactory.openSession();

    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    User user = new User();
    user.setSex("1");
    user.setUsername("张小明");
    List<User> users = userMapper.selectUserBySexAndUsername(user);
    for (User user2 : users) {
        System.out.println(user2);
    }
}

2.2、动态SQL之SQL片段

Sql中可将重复的sql提取出来,使用时用include引用即可,最终达到sql重用的目的。
将select * from user提取出来:

<mapper namespace="com.itheima.mybatis.mapper.UserMapper">
    <sql id="selector">
        select * from user
    </sql>
    <!--    根据性别和名字查询用户  where 可以去掉第一个前ANd   -->
     <select id="selectUserBySexAndUsername" parameterType="User" resultType="User">
        <include refid="selector"/>
        <where>
            <if test="sex != null and sex != ''">
                 and sex = #{sex} 
            </if>
            <if test="username != null and username != ''">
                 and username = #{username}
            </if>
        </where>
     </select>
</mapper>

2.3、动态SQL之foreach标签

根据多个id查询用户信息
查询sql:

SELECT * FROM user WHERE id IN (1,10,24)

接口:

public interface UserMapper {
    //根据多个id查询用户信息  
//  public List<User> selectUserByIds(Integer[] ids);
//  public List<User> selectUserByIds(List<Integer> ids); 
    public List<User> selectUserByIds(QueryVo vo);
}

QueryVO:

public class QueryVo implements Serializable {
    private static final long serialVersionUID = 1L;
    private User user;

    List<Integer> idsList;

    //Integer[] ids;

    public List<Integer> getIdsList() {
        return idsList;
    }
    public void setIdsList(List<Integer> idsList) {
        this.idsList = idsList;
    }
    public Integer[] getIds() {
        return ids;
    }
    public void setIds(Integer[] ids) {
        this.ids = ids;
    }
    public User getUser() {
        return user;
    }
    public void setUser(User user) {
        this.user = user;
    }
}

如果用的是QueryVO,那么UserMapper.xml:

<select id="selectUserByIds" parameterType="QueryVo" resultType="User">
    <include refid="selector"/>
    <where>
        <foreach collection="idsList" item="id" separator="," open="id in (" close=")">
            #{id}
        </foreach>
    </where>
 </select>

测试:

//多个ID
@Test
public void testfindUserIDs() throws Exception {
    //加载核心配置文件
    String resource = "sqlMapConfig.xml";
    InputStream in = Resources.getResourceAsStream(resource);
    //创建SqlSessionFactory
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
    //创建SqlSession
    SqlSession sqlSession = sqlSessionFactory.openSession();

    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    List<Integer> ids  = new ArrayList<>();
    ids.add(16);
    ids.add(22);
    ids.add(24);
    QueryVo vo = new QueryVo();
    vo.setIdsList(ids);

    List<User> users = userMapper.selectUserByIds(ids);
    for (User user2 : users) {
        System.out.println(user2);
    }
}

如果用的是数组,那么接口:

public List<User> selectUserByIds(Integer[] ids);

UserMapper.xml:

<!-- 多个ID (1,2,3)-->
 <select id="selectUserByIds" parameterType="QueryVo" resultType="User">
    <include refid="selector"/>
    <where>
        <foreach collection="array" item="id" separator="," open="id in (" close=")">
            #{id}
        </foreach>
    </where>
 </select>

测试:

@Test
public void testfindUserIDs() throws Exception {
    //加载核心配置文件
    String resource = "sqlMapConfig.xml";
    InputStream in = Resources.getResourceAsStream(resource);
    //创建SqlSessionFactory
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
    //创建SqlSession
    SqlSession sqlSession = sqlSessionFactory.openSession();

    UserMapper userMapper = sqlSession.getMapper(UserMapper.class); 

    Integer[] ids = new Integer[3];
    ids[0] = 16;
    ids[2] = 22;
    ids[1] = 24;
    List<User> users = userMapper.selectUserByIds(ids);
    for (User user2 : users) {
        System.out.println(user2);
    }
}

三、关联查询

3.1、一对一查询

因为一个订单信息只会是一个人下的订单,所以从查询订单信息出发关联查询用户信息为一对一查询。

3.1.1、方法一:使用resultType

使用resultType,改造订单pojo类,此pojo类中包括了订单信息和用户信息,这样返回对象的时候,mybatis自动把用户信息也注入进来了。
OrderUser类继承Order类后OrderUser类包括了Order类的所有字段,只需要定义用户的信息字段即可:

public calss OrderUser extends Order{
    private String username;
    private String address;
}

Mapper.xml:

<!-- 
//一对一关联 查询  以订单为中心 关联用户
public List<Orders> selectOrders();
-->
 <resultMap type="Orders" id="order">
    <result column="id" property="id"/>
    <result column="user_id" property="userId"/>
    <result column="number" property="number"/>
    <!-- 一对一 -->
    <association property="user" javaType="User">
        <id column="user_id" property="id"/>
        <result column="username" property="username"/>
    </association>
 </resultMap>
<select id="queryOrderUser" resultType="orderUser">
    SELECT
    o.id,
    o.user_id
    userId,
    o.number,
    o.createtime,
    o.note,
    u.username,
    u.address
    FROM
    `order` o
    LEFT JOIN `user` u ON o.user_id = u.id
</select>

Mapper接口:

List<OrderUser> queryOrderUser();

测试:

@Test
public void testQueryOrderUser() {
    // mybatis和spring整合,整合之后,交给spring管理
    SqlSession sqlSession = this.sqlSessionFactory.openSession();
    // 创建Mapper接口的动态代理对象,整合之后,交给spring管理
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

    // 使用userMapper执行根据条件查询用户
    List<OrderUser> list = userMapper.queryOrderUser();

    for (OrderUser ou : list) {
        System.out.println(ou);
    }

    // mybatis和spring整合,整合之后,交给spring管理
    sqlSession.close();
}

运行结果:
这里写图片描述

3.1.2、方法二:使用resultMap

使用resultMap,定义专门的resultMap用于映射一对一查询结果。
改造pojo类:

public class Orders  implements Serializable{
    private static final long serialVersionUID = 1L;
    private Integer id;
    private Integer userId;
    private String number;
    private Date createtime;
    private String note;

    //附加对象  用户对象
    private User user;
}

接口:

public interface OrderMapper {
    //一对一关联 查询  以订单为中心 关联用户
    public List<Orders> selectOrders();
}

OrderMapper.xml:

<!-- 
    //一对一关联 查询  以订单为中心 关联用户
    public List<Orders> selectOrders();
 -->
 <resultMap type="Orders" id="order">
    <result column="id" property="id"/>
    <result column="user_id" property="userId"/>
    <result column="number" property="number"/>
    <!-- 一对一 -->
    <association property="user" javaType="User">
        <id column="user_id" property="id"/>
        <result column="username" property="username"/>
    </association>
 </resultMap>
 <select id="selectOrders" resultMap="order">
    SELECT 
    o.id,
    o.user_id, 
    o.number,
    o.createtime,
    u.username 
    FROM orders o 
    left join user u 
    on o.user_id = u.id
 </select>

测试:

@Test
public void testOrderList() throws Exception {
    //加载核心配置文件
    String resource = "sqlMapConfig.xml";
    InputStream in = Resources.getResourceAsStream(resource);
    //创建SqlSessionFactory
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
    //创建SqlSession
    SqlSession sqlSession = sqlSessionFactory.openSession();

    //SqlSEssion帮我生成一个实现类  (给接口)
    OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class);
    List<Orders> selectOrdersList = orderMapper.selectOrders();

    for (Orders orders : selectOrdersList) {
        System.out.println(orders);
    }
}

3.2、一对多查询

改造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;// 地址

    //附加对象List
    private List<Orders> ordersList;
}

接口:

public interface OrderMapper {
    //一对多关联
    public List<User> selectUserList();
}

Mapper.xml:

 <!-- 
    //一对多关联
    public List<User> selectUserList(); 
-->
    <resultMap type="User" id="user">
        <id column="user_id" property="id"/>
        <result column="username" property="username"/>
        <!-- 一对多 -->
        <collection property="ordersList" ofType="Orders">
            <id column="id" property="id"/>
            <result column="number" property="number"/>
        </collection>
    </resultMap>
    <select id="selectUserList" resultMap="user">
        SELECT 
        o.id,
        o.user_id, 
        o.number,
        o.createtime,
        u.username 
        FROM user u
        left join orders o 
        on o.user_id = u.id
    </select>

测试:

@Test
public void testUserList() throws Exception {
    //加载核心配置文件
    String resource = "sqlMapConfig.xml";
    InputStream in = Resources.getResourceAsStream(resource);
    //创建SqlSessionFactory
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
    //创建SqlSession
    SqlSession sqlSession = sqlSessionFactory.openSession();

    //SqlSEssion帮我生成一个实现类  (给接口)
    OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class);
    List<User> users = orderMapper.selectUserList();
    for (User user : users) {
        System.out.println(user);
    }
}

转载请标明出处,原文地址:https://blog.csdn.net/weixin_41835916 总结整理不容易,如果觉得本文对您有帮助,请点击支持一下,您的支持是我写作最大的动力,谢谢。
这里写图片描述

猜你喜欢

转载自blog.csdn.net/weixin_41835916/article/details/80898491
今日推荐