JavaWeb之Mybatis进阶

MyBatis三种开发方式

接口代理的开发方式(重点)

使用注解的开发方式(重点)

传统DAO实现类的开发方式(目前淘汰,因为分布式的使用)

mybatis中的sql

参数占位符:

#{}:先使用?占位,执行SQL时将具体值赋值给?

${}:拼SQL,会存在SQL注入问题

parameterType:

用于设置参数类型,该参数可以省略

SQL语句中特殊字符处理:

转义字符

<![CDATA[ 内容 ]]>:CD提示
<select id="selectById" resultType="User">
        select * from user where id = #{id};
        <!--
        select * from user where id = #{id};预编译,sql语句中用?占位
        select * from user where id = ${id}; 拼接SQL
        在<select>等标签中不能打ctrl+/注释,是不会完全注释gL语句的,必须用这种注释
        parameterType属性: 传入参数的属性,可以省略,所以建议不写
        resultType属性:方法的返回类型,主要是对象,如果是增删改返回影响行数的,不要写
                        当数据库字段名和类的成员变量名一致的时候,使用
        select * from user where id &lt;#lid}; 遇到<等符号,需要使用转义符
        -->
    </select>

事务

查询数据可以直接查不会出错

但是增删改必须要开启事务,因为在mybaits中默认不会自动提交

事务两种开启方式:

在sqlSessionFactory.openSession(true);

sqlSession.commit()

增删改查

删除

1.在接口中添加方法

2.在接口映射文件UserMapper.xml配置SQL语句

3.执行方法

1.在接口中添加方法
void deleteById(int id);

2.在接口映射文件UserMapper.xml配置SQL语句
<delete id="deleteById"> delete from user where id = #{id}; </delete>

3.执行方法

@Test
    public void test3() throws IOException {

        //因为要使用mybatis,所以要把配置文件mybatis-config.xml加载过来(在测试案例访问resoureces的资源,可以直接访问文件)
        InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
        //将这个文件转为流的形式,这个流会自动关闭,然后使用这个流获取连接,首先获得连接的builder对象
        //这个builder需要new
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //到这步获得了连接的工厂类,接下来通过工厂类获得连接
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //成功获得连接,使用这个连接将接口使用动态代理生成对象
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);//因为是动态代理所以用.class
        //用代理对象调用接口中的方法
        mapper.deleteById(3);
        //提示成功,但是实际上确删除不成功,这是因为mybatis的事务
        //在进行增删改的操作,要提交事务,mybatis事务的自动提交默认时关闭的
        //有两种设置事务的方法,1.在sqlSessionFactory.openSession(true);2.sqlSession.commit()
        sqlSession.commit();

        //关闭资源,只需要关闭sqlSession
        sqlSession.close();
    }

修改

int update(User user);

<update id="update">
        UPDATE user
        SET username = #{username},
            birthday =#{birthday},
            sex=#{sex},
            address=#{address}
        WHERE id = #{id};
    </update>
@Test
    public void test4() throws IOException {

        //因为要使用mybatis,所以要把配置文件mybatis-config.xml加载过来(在测试案例访问resoureces的资源,可以直接访问文件)
        InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
        //将这个文件转为流的形式,这个流会自动关闭,然后使用这个流获取连接,首先获得连接的builder对象
        //这个builder需要new
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //到这步获得了连接的工厂类,接下来通过工厂类获得连接
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //成功获得连接,使用这个连接将接口使用动态代理生成对象
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);//因为是动态代理所以用.class
        //用代理对象调用接口中的方法
        User user = new User(1, "cat", Date.valueOf("2022-01-11"), "男", "地球");
        mapper.update(user);
        //提示成功,但是实际上确删除不成功,这是因为mybatis的事务
        //在进行增删改的操作,要提交事务,mybatis事务的自动提交默认时关闭的
        //有两种设置事务的方法,1.在sqlSessionFactory.openSession(true);2.sqlSession.commit()
        sqlSession.commit();

        //关闭资源,只需要关闭sqlSession
        sqlSession.close();
    }

插入

插入并获取新的主键值

int add(User user);
<!--useGeneratedKeys 获取数据库中生成的主键   keyProperty 将获取到的主键放到那个属性中 -->
    <insert id="add" useGeneratedKeys="true" keyProperty="id">
        INSERT INTO user
        VALUES (null, #{username}, #{birthday}, #{sex}, #{address});
    </insert>
@Test
    public void test5() throws IOException {

        //因为要使用mybatis,所以要把配置文件mybatis-config.xml加载过来(在测试案例访问resoureces的资源,可以直接访问文件)
        InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
        //将这个文件转为流的形式,这个流会自动关闭,然后使用这个流获取连接,首先获得连接的builder对象
        //这个builder需要new
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //到这步获得了连接的工厂类,接下来通过工厂类获得连接
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //成功获得连接,使用这个连接将接口使用动态代理生成对象
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);//因为是动态代理所以用.class
        //用代理对象调用接口中的方法
        User user = new User(10086, "dog", Date.valueOf("1980-10-24"), "男", "地球");
        System.out.println(user.getId());
        int row = mapper.add(user);
        System.out.println(row);
        System.out.println(user.getId());
        //提示成功,但是实际上确删除不成功,这是因为mybatis的事务
        //在进行增删改的操作,要提交事务,mybatis事务的自动提交默认时关闭的
        //有两种设置事务的方法,1.在sqlSessionFactory.openSession(true);2.sqlSession.commit()
        sqlSession.commit();

        //关闭资源,只需要关闭sqlSession
        sqlSession.close();
    }

多参数处理

当只有一个参数时,在xml中编写sql时可以使用传入的参数名,但是多参数的时候不能直接用参数名

select

	//多参数
    //报错Available parameters are [arg1, arg0, param1, param2]
    //方案1,散装,用@Param给咱们的参数起个名字
    //List<User> selectByCondition(@Param("username") String username, @Param("sex") String sex);
    //方案2,使用对象封装
    //List<User> selectByCondition(User user);
    //方案3,使用Map集合封装
    List<User> selectByCondition(Map<String,String> map);
<select id="selectByCondition" resultType="com.jwl.pojo.User">
        <!--
            select * from user where username = #{username} and sex = #{sex};
            //报错Available parameters are [arg1, arg0, param1, param2]
             因为传多参数时,默认是用arg或者param这种形式,arg从0开始,param从1开始
             这样用:select * from user where username = #{arg0} and sex = #{arg1};

             但是如果参数过多,使用这种默认方式太过麻烦,要是我们还想使用传入的参数名,有三种解决方案:
             1.散装。在接口中定义参数
        -->
        select * from user where username like #{username} and sex = #{sex};

    </select>

动态sql

sql语句并不是固定不变的,要根据条件编写合适的sql语句

if标签

select if标签 where标签

//动态sql
    List<User> selectByIf(@Param("username") String username, @Param("sex") String sex);
<select id="selectByIf" resultType="com.jwl.pojo.User">
        <!--
            两个条件同时满足时,成功查询
            若是两个都不输入则sql为select * from user where,出现报错
            但是,若是不输入username ,只输入sex, 那么拼接的sql将为select * from user where and sex = ?  出现报错
            思考:都不输入时,这个where怎么去掉?  只输入sex时,and怎么去掉?
            mybatis为了解决这个问题,把where做成了标签<where>
            <where>在需要where的时候会补上,并且将多余的and或or带走
            (需要他的时候就会出现,并且帮忙解决其他麻烦,比如带走and ,像极了女神的舔狗们)
        -->

        select * from user
        <where>
            <if test="username!=null and username != ''">
                username = #{username}
            </if>

            <if test="sex != null and sex !=''">
                and sex = #{sex};
            </if>
        </where>

    </select>

update set标签

//这样new一个user,再通过set方法传入数据,如果没传入数据的字段就会是null,会把数据库中不准备修改的数据变为Null
    //为了避免这种情况,也要加入if标签来判断
    int updateByIf(User user);
<update id="updateByIf">
        <!--
        这样new一个user,再通过set方法传入数据,如果没传入数据的字段就会是null,会把数据库中不准备修改的数据变为Null
        为了避免这种情况,也要加入if标签来判断
        UPDATE user
        SET username = #{username},
        birthday =#{birthday},
        sex=#{sex},
        address=#{address}
        WHERE id = #{id};

        加上if标签,还是存在一个问题,每一个if标签中sql中都有一个逗号,会产生语法错误
        mysbatis将set做成标签<set>代替set同时去掉多余的逗号
        -->
        UPDATE user
        <set>
            <if test="username !=null and username != ''">
                username = #{username},
            </if>

            <if test="birthday !=null"><!--birthday这里不能判断为'',因为Date类型和String类型比较会报错 -->
                birthday = #{birthday},
            </if>
            <if test="sex !=null and sex != ''">
                sex = #{sex},
            </if>
            <if test="address !=null and address != ''">
                address = #{address},
            </if>
        </set>

        WHERE id = #{id};
    </update>

批量删除 foreach标签

void deleteByIds(int[] ids);
<!--
        批量删除,传入的参数是一个数组,思考一下,where中应该用in
        在mybatis中有专门的对于数组,集合的标签<foreach>
        我们原意是要 delete from user where id in (?,?,?);
        collection表示传入的数组或者集合,数组默认名字叫做array,如果是集合默认名字为list
        item表示数组或集合中的一项
        open遍历前加的内容
        close遍历后加的内容
        separator表示分隔符
     -->
    <delete id="deleteByIds">
        delete from user where id in
        <!--直接写在collection中直接写ids会报错,必须要么用散装方式给参数设定个名字,要么默认用array -->
        <foreach collection="array" item="id" open="(" close=")" separator=",">
            #{id}
        </foreach>
    </delete>

choose标签
跟java的switch类似

List<User> selectBySex(int sex);
<select id="selectBySex" resultType="com.jwl.pojo.User">
        select * from user
        <where>
            <choose>
                <when test="sex==1">
                    sex = '男';
                </when>
                <when test="sex==0">
                    sex = '女';
                </when>
                <otherwise>
                    sex = '女';
                </otherwise>
            </choose>
        </where>
    </select>

sql标签

<select id="selectAll" resultType="User">
        select
        <include refid="useAll"/>
        from user;
    </select>

    <!-- sql标签:可以抽取一部分的公用代码
         id属性:唯一的标识,别的地方可以通过这个id找到这个标签
         include标签:引入sql标签抽取的内容
         refid属性:抽取的sql标签的id

         像下面这个sql标签就抽取的*的内容
     -->
    <sql id="useAll">
        id
        ,username,birthday,sex,address
    </sql>

ResultMap

在上述的例子中都是数据库字段名和实体类名相同,查询方便

但是很多情况下数据库字段名和实体类名不同

因为数据库字段名和实体类的属性名不一致,查到的数据封装不到Order中,
解决方法有三种

1.取别名,在写sql时,取对应实体类的别名

2.在mybaits配置文件中的标签中设置自动将数据库和实体类名称转换< setting name=“mapUnderscoreToCamelCase” value=“true”/>,默认为关闭

3.使用resultMap

<settings>
        <!--在控制台显示SQL语句 打印日志-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
<resultMap id="OrderMap" type="Order">
        <id column="o_id" property="oId"/>
        <result column="user_id" property="userId"/>
        <result column="create_time" property="createtime"/>
    </resultMap>
    <select id="selectAllBy" resultMap="OrderMap">
        select * from tb_order;
    </select>

最后

如果你对本文有疑问,你可以在文章下方对我留言,敬请指正,对于每个留言我都会认真查看。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值