mybatis学习笔记2

mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- 注意顺序 -->
    <!-- db.properties文件在resources下 -->
    <properties resource="db.properties"/>

    <settings>
        <!-- 设置使用log4j日志 -->
        <setting name="logImpl" value="LOG4J"/>
        <!-- 开启下划线转驼峰 -->
        <!-- 把数据库create_time,变成createTime列 -->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>

    <!-- 类型别名 -->
    <typeAliases>
        <!-- 这样是给每一个类单独设置别名 -->
        <!--<typeAlias alias="User" type="com.qf.model.User"/>-->

        <!-- 这样可以直接设置整个包下所有类都有别名,且别名就是类名 -->
        <package name="com.qf.model"/>
    </typeAliases>

    <!-- 插件 分页-->
    <plugins>
        <!-- 插件拦截器的路径 -->
        <plugin interceptor="com.github.pagehelper.PageInterceptor"/>
    </plugins>

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <!- - 数据源POOLED就是开启使用数据库连接池技术这是mybatis自己的技术 -->
<!--            <dataSource type="POOLED">-->
            <dataSource type="com.qf.Util.MyDruidDataSourceFactory">
<!--                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>-->
<!--                <property name="url" value="jdbc:mysql://localhost:3306/mysql02?serverTimezone=UTC&amp;&amp;useSSL=false"/>-->
<!--                <property name="username" value="root"/>-->
<!--                <property name="password" value="585858"/>-->
<!--                <!- - 数据库连接的配置 -->
                <property name="driverClass" value="${jdbc.driver}"/>
                <property name="jdbcUrl" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>
   <!-- 映射器 -->
    <mappers>
        <!-- 这种方式会随着功能变多,加载文件变多,代码臃肿 -->
        <!--<mapper resource="UserMapper.xml"/>-->

        <!--package来指定一个包,该包下映射文件会全部加载 -->
        <package name="com.qf.mapper"/>
        
    </mappers>
</configuration>

分页

  @Test
    public void selectAll(){
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        //参数1:当前页
        //参数2:每页大小
//        PageHelper.startPage(2,2);
        List<User> list = userMapper.FindByall();
        PageInfo<User> pageInfo = new PageInfo<>(list);
//        System.out.println("总条数"+pageInfo.getTotal());//获得总条数
//        System.out.println("总页数"+pageInfo.getPages());//获得总页数
//        System.out.println("当前页的数据"+pageInfo.getList());//获得总数据(当前页的数据)
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }
    }

2.映射文件

2.1resultMap 【重点】

result map --> 结果映射

结果: sql语句的结果

映射: sql语句的结果和实体类的映射
斜体样式
自动映射(查询结果自动封装到实体类)? 字段列名和实体类属性一致,就会自动封装

***那有些字段和属性名不一致,导致映射失败 —> 手动映射 --> resultMap ***

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.qf.mapper.UserMapper">

    <!--开始手动映射: 将列名和属性名一一对应 -->
    <resultMap id="userResultMap" type="User">
        <!-- id标签,用来映射主键列 -->
        <id column="uid" property="id"/>
        <!-- 其他列,就是使用result标签 -->
        <result column="name" property="username"/>
        <result column="pwd" property="password"/>
        <result column="tel" property="phone"/>
        <!-- 其他列,列名和属性一致,可以不用设置,会自动封装 -->
    </resultMap>

    <!-- 当自动封装失败,就使用手动映射 -->
    <!-- 使用手动映射时,就不在设置resultType,而是设置resultMap指定那个id-->
    <select id="findUserById" resultMap="userResultMap">
        SELECT id uid,username name,password pwd,phone tel,create_time, money,sex
        FROM tb_user WHERE id = #{id}
    </select>
</mapper>

3.多表查询

3.1一对一

例如一个商品对应一个购买者。User–>Order分别创建实体类,但是的实体类,只有订单信息,我们要查询的是订单和用户! 上面的类就无法展现全部数据,所以需要扩展类

public class OrderVO extends Order {
    private User user;
    // set get
}

OrderMapper.java接口文件

public interface OrderMapper {
    OrderVO findOrderWithUserById(int oid);
}

继承Order类,创建User类
OderMapper.xml文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.qf.Mapper.OrderMapper">

    <resultMap id="OrderVOUser" type="com.qf.model.OrderVO">
        <!--封装查询主体Order-->
        <id column="oid" property="oid"/>
        <result column="order_time" property="orderTime"/>
        <result column="order_desc" property="orderDesc"/>
        <result column="uid" property="uid"/>
            <!-- 一对一映射,需要封装关联的User对象 -->
            <!-- 一对一映射,需要特殊标签 association-->
            <association property="user" javaType="com.qf.model.User">
                <!-- 下面正常的列和属性一一映射 -->
                <id column="id" property="id"/>
                <result column="username" property="username"/>
                <result column="password" property="password"/>
                <result column="phone" property="phone"/>
                <result column="create_time" property="createTime"/>
                <result column="money" property="money"/>
                <result column="sex" property="sex"/>
            </association>

    </resultMap>
    <!-- 多表联查,直接返回resultType无法封装关联的那个对象,就使用使用resultMap手动映射 -->
<select id="ordervoById" resultMap="OrderVOUser">
    select*from tb_order o,tb_user u where o.uid=u.id and o.oid=1
</select>
</mapper>

测试

    @Test
    public void findOrderWithUserById() {
        OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
        OrderVO orderVO = mapper.findOrderWithUserById(1);

        // 获得订单信息
        int oid = orderVO.getOid( );
        System.out.println("oid = " + oid);
        Date orderTime = orderVO.getOrderTime( );
        System.out.println("orderTime = " + orderTime);
        String orderDesc = orderVO.getOrderDesc( );
        System.out.println("orderDesc = " + orderDesc);
    
        // 获得订单一家关联的用户信息
        User user = orderVO.getUser( );
        System.out.println(user );
    }

3.1一对多

目的查询用户,以及关联多个订单,User类不够展现全部数据,那么就创建扩展类UserVO,UserVO类继承User就可以存储用户信息,还需要再UserVO类中添加Order类来存储信息,但是!!不是一个Order类,因为是一对多,一个用户关联多个订单,所有要设置List<Order>

public class UserVO extends User{

    private List<Order> orderList;

    @Override
    public String toString() {
        String s = super.toString( );
        return s +" \r\n UserVO{" +
                "orderList=" + orderList +
                '}';
    }

    public List<Order> getOrderList() {
        return orderList;
    }

    public void setOrderList(List<Order> orderList) {
        this.orderList = orderList;
    }
}

UserMapper.java接口

public interface UserMapper {
    UserVO findUserWithOrdersById(int id);
}

UserMapper.xml

 <!-- 一对多 -->
    <resultMap id="userWithOrdersResultMap" type="UserVO">
        <!-- 封装User对象 -->
        <id column="id" property="id"/>
        <result column="username" property="username"/>
        <result column="password" property="password"/>
        <result column="phone" property="phone"/>
        <result column="create_time" property="createTime"/>
        <result column="money" property="money"/>
        <result column="sex" property="sex"/>
        <!-- 一对多关联映射使用collection标签 -->
        <!-- property是UserVO类中关联的属性 -->
        <!-- 不是javaType,是ofType,是指定集合中存储的数据类型 -->
        <collection property="orderList" ofType="com.qf.model.Order">
            <id column="oid" property="oid"/>
            <result column="order_time" property="orderTime"/>
            <result column="order_desc" property="orderDesc"/>
            <result column="uid" property="uid"/>
        </collection>
    </resultMap>

    <!-- 多表联查,另外的属性不会自动封装,需要使用resultMap -->
    <select id="findUserWithOrdersById" resultMap="userWithOrdersResultMap">
        SELECT
        *
        FROM
        tb_user u
        LEFT JOIN tb_order o ON u.id = o.uid
        WHERE
        u.id = #{id}
    </select>

4 动态SQL【重点】

理解: 帮助我们拼接SQL
常见的动态SQL语法

  • SQL片段(官方不是在动态SQL章节)
  • where , if
  • set
  • trim
  • foreach

4.1 SQL片段

减少代码重复,主要用于抽取字段,表名等

<!-- 将重复的SQL代码抽取成SQL片段,以供复用 -->
    <sql id="userField">
        id,username,password,phone,create_time,money,sex
    </sql>
    <select id="findAll" resultType="User">
        select
            <!-- 引入片段 -->
            <include refid="userField"/>
        from
            tb_user
    </select>

4.2 if

UserMapper.java

public interface UserMapper {
    // 为了演示动态sql的if
    List<User> findUserBySex(@Param("sex") int sex, @Param("password") String password);

}

UserMapper.xml

 <select id="findUserBySex" resultType="User">
        select
            <include refid="userField"/>
        from tb_user where sex = #{sex}
        <!-- 动态判断 -->
        <if test="password != null">
            and password = #{password}
        </if>
    </select>

测试

    @Test
    public void testIf(){
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        // 传入密码,SQL语句就拼接【看日志中发出的SQL】
        // List<User> list = mapper.findUserBySex(1, "123456");

        // 没传入密码,SQL语句就不拼接【看日志中发出的SQL】
        List<User> list = mapper.findUserBySex(1,null);
        for (User user : list) {
            System.out.println(user );
        }
    }

4.3where

有条件时帮我们拼接where关键词,没有条件查询时,不拼接where,一般会where和if一起用。

<select id="findUserBySex2" resultType="User">
        select
            <include refid="userField"/>
        from
            tb_user
        <where>
            <if test="sex != null">
                sex = #{sex}
            </if>
        </where>
    </select>

4.4set

动态更新语句的类似解决方案叫做 setset 元素可以用于动态包含需要更新的列,忽略其它不更新的列
UserMapper.java

public interface UserMapper {
    int updateUser(User user);
}

UserMapper.xml

 <!-- set完成动态更新 -->
    <update id="updateUser">
        update tb_user
        <!-- set标签自动拼接SET关键词 -->
        <set>
            <!-- 会自动过滤最后一个, -->
            <!-- 特别注意,因为判断条件是!=null,基本不可能为null,所以将基本类型变为包装类 -->
            <if test="username != null">username = #{username},</if>
            <if test="password != null">password = #{password},</if>
            <if test="phone != null">phone = #{phone},</if>
            <if test="createTime != null">create_time = #{createTime},</if>
            <if test="money != null">money = #{money},</if>
            <if test="sex != null">sex = #{sex},</if>
        </set>
        where id = #{id}
    </update>

测试

    @Test
    public void testUpdate(){
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = new User( );
        user.setId(1);
        // 只更新这个2字段,其他字段不动
        user.setUsername("HHH");
        user.setPassword("qK666");

        int i = mapper.updateUser(user);
        System.out.println(i > 0?"OK":"REE" );
        // 增删改要提交
        sqlSession.commit();
    }

4.5 foreach

场景: 批量删除
delete from tb_user where id in (1,2,3,…);
UserMapper.java

public interface UserMapper {
    // 为了演示动态sql foreach
    int deleteBatch(List<Integer> ids);
}

UserMapper.xml

<!-- 动态sql foreach -->
    <delete id="deleteBatch">
        delete from tb_user
        where id in
        <!--
           <foreach>开始循环,取出集合中的数据
           collection,要遍历的集合,此处必须写list (或者可以写collection,arg0,不能写别的)
           item , 遍历得到结果,命名任意,但是下面#{}内的名字要和这里一致
        -->
        <foreach collection="list" item="id" open="(" separator="," close=")">
            #{id}  
        </foreach>
    </delete>

测试

 /**
     * 测试foreach
     */
    @Test
    public void testForeach(){
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        ArrayList<Integer> list = new ArrayList<>( );
        list.add(31);
        list.add(32);
        list.add(33);
        int i = mapper.deleteBatch(list);
        System.out.println("i = " + i);
        System.out.println(i > 0?"OK":"ERR" );
        // 增删改要提交
        sqlSession.commit();
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

想要入门的程序猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值