上文中说道SqlSession执行语句时的用法,不过现在有了一种更简洁的方式 ——使用正确描述每个语句的参数和返回值的接口(比如 UserMapper.class),你现在不仅可以执行更清晰和类型安全的代码,而且还不用担心易错的字符串字面值以及强制类型转换。

文件层次如图:

    

代码示例:

@AllArgsConstructor
@NoArgsConstructor
@Getter@Setter
@ToString
@Alias("User")
public class User {
    private Integer id;
    private String username;
    private String password;
    private Date date;
    private BigDecimal salary;
}
beanUser(使用了lombok插件)
public interface IUserService {
    void save(User user);
    void delete(Integer id);
    void update(User user);
    User find(Integer id,String username);
    List<User> findAll();
    List<User> findOrderByColumn(String column);
    void deleteSelectAll(int[] ids);
}
IUserService接口
public class UserServiceImpl implements IUserService {
    
    @Override
    public void save(User user) {
        SqlSession session = MybatisUtil.getSession();
        /*MAP接口的代处理对象*/
        UserMapper um = session.getMapper(UserMapper.class);
        um.save(user);
        session.commit();
        session.close();
    }

    @Override
    public void delete(Integer id) {
        SqlSession session = MybatisUtil.getSession();
        /*MAP接口的代处理对象*/
        UserMapper um = session.getMapper(UserMapper.class);
        um.delete(id);
        session.commit();
        session.close();
    }

    @Override
    public void update(User user) {
        SqlSession session = MybatisUtil.getSession();
        /*MAP接口的代处理对象*/
        UserMapper um = session.getMapper(UserMapper.class);
        um.update(user);
        session.commit();
        session.close();
    }

    @Override
    public User find(Integer id,String username) {
        SqlSession session = MybatisUtil.getSession();
        /*MAP接口的代处理对象*/
        UserMapper um = session.getMapper(UserMapper.class);
        User user = um.find(id, username);
        session.close();
        return user;
    }

    @Override
    public List<User> findAll() {
        SqlSession session = MybatisUtil.getSession();
        /*MAP接口的代处理对象*/
        UserMapper um = session.getMapper(UserMapper.class);
        List<User> all = um.findAll();
        session.close();
        return all;
    }

    @Override
    public List<User> findOrderByColumn(String column) {
        SqlSession session = MybatisUtil.getSession();
        /*MAP接口的代处理对象*/
        UserMapper um = session.getMapper(UserMapper.class);
        List<User> orderByColumn = um.findOrderByColumn(column);
        session.close();
        return orderByColumn;
    }

    @Override
    public void deleteSelectAll(int[] ids) {
        SqlSession session = MybatisUtil.getSession();
        /*MAP接口的代处理对象*/
        UserMapper um = session.getMapper(UserMapper.class);
        um.deleteSelectAll(ids);
        session.commit();
        session.close();
    }
}
UserServiceImpl
public interface UserMapper {
    void save(User user);
    void delete(Integer id);
    void update(User user);
    User find(@Param("id") Integer id,@Param("username") String username);
    List<User> findOrderByColumn(@Param("column") String column);
    List<User> findAll();
    void deleteSelectAll(int[] ids);
}
UserMapper
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace:写UserMapper接口的全限定名-->
<mapper namespace="com.test.mapper.UserMapper">
    <!--  #{}表示调用对象中响应的get方法-->
    <!--  注意,这里的标签中的id值是唯一的
    因为在UserMapper的底层是将namespace和id一起作为一个Map集合的key,sql语句作为value,因为map的key唯一,所以id必须唯一 -->  
    <!--  保存  -->
    <!--useGeneratedKeys为true表示返回主键的值 keyProperty表示返回给对象的哪个属性-->
    <insert id="save" useGeneratedKeys="true" keyProperty="id">
        insert into user values(null,#{username},#{password},#{date},#{salary})
    </insert>

    
    <!--  删除  -->
    <delete id="delete">
        delete from user where id=#{id}
    </delete>
    <!--批量删除-->
    <delete id="deleteSelectAll">
        delete from user where id in 
        <foreach collection="array" open="(" close=")" item="item" separator=",">
            #{item}
        </foreach>
    </delete>

    <!--  更新  -->
    <update id="update">
        update user
        <trim prefix="set" suffixOverrides=",">
            <if test="username!=null">
                username=#{username},
            </if>
            <if test="password!=null">
                password=#{password},
            </if>
            <if test="date!=null">
                date=#{date},
            </if>
            <if test="salary!=null">
                salary=#{salary},
            </if>
        </trim>
        where id=#{id}
    </update>

    <!--type:把结果集封装成对象的类型-->
    <resultMap id="myResultMap" type="User">
        <id column="id" property="id"/>
        <result column="username" property="username"/>
        <result column="password" property="password"/>
        <result column="date" property="date"/>
        <result column="salary" property="salary"/>
    </resultMap>

    <!--  查询一个  -->
    <!--<select id="find" resultMap="myResultMap">
        select * from user where 1=1
        <if test="username !=null">
            and username = #{username}
        </if>
        <if test="id != null">
            and id = #{id}
        </if>
    </select>-->
    <select id="find" resultMap="myResultMap">
        select * from user
        <where>
            <if test="username !=null">
                username = #{username}
            </if>
            <if test="id != null">
                and id = #{id}
            </if>
        </where>
    </select>

    <!--  查询全部 -->
    <select id="findAll" resultType="User">
        select * from user
    </select>

    <!--通过列名降序查询-->
    <select id="findOrderByColumn" resultType="User">
        select * from user order by ${column} desc
    </select>

</mapper>
UserMapper.xml

几个知识点介绍:重点

1、Mapper接口的使用方式及原理

  1.mapper映射文件中的namespace的值,必须等于mapper接口的全限定名

  2.mapper映射文件中的Sql的id,必须等于mapper接口中的方法名

  3.mapper映射文件中的Sql的paramterType必须跟对应的方法的类型相同

  4.方法的返回值必须和resultType或者resultMap的值保持一致

  以Update为例,图中解释了update的原理

2、保存数据自动获取数据库生成的主键

    <!--useGeneratedKeys为true表示返回主键的值
     keyProperty表示返回给对象的哪个属性-->
    <insert id="save" useGeneratedKeys="true" keyProperty="id">
        insert into user values(null,#{username},#{password},#{date},#{salary})
    </insert>

3、resultMap的使用与where的作用  以及if的作用

<!--resultMap:结果集映射标签
    type:把结果集封装成对象的类型
    id:当前结果集映射的唯一标识

    在列名与属性名不一致时使用这两个标签进行转换
    column:数据库中的列名
    property:类中的属性名
-->
    <resultMap id="myResultMap" type="User">
        <id column="id" property="id"/>
        <result column="username" property="username"/>
        <result column="password" property="password"/>
        <result column="date" property="date"/>
        <result column="salary" property="salary"/>
    </resultMap>

    <!--  查询  -->
    <!--  where标签
    自动拼接里面的sql语句,当where里面没有成立的条件时,则什么都没有
    如果里面有条件成立,则自动为语句前加上where ,若语句为and开头,则自动删除and

    if标签
    if test="判断条件" 如果条件成立,则执行if中间的语句,与jstl用法相同
-->
  
<select id="find" resultMap="myResultMap"> select * from user <where> <if test="username !=null"> username = #{username} </if> <if test="id != null"> and id = #{id} </if> </where> </select>

4、动态sql

  if  上面已经介绍过了

  choose 类似与java中的switch

<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG WHERE state = ‘ACTIVE’
  <choose>
    <when test="title != null">
      AND title like #{title}
    </when>
    <when test="author != null and author.name != null">
      AND author_name like #{author.name}
    </when>
    <otherwise>
      AND featured = 1
    </otherwise>
  </choose>
</select>

  where 上面已经介绍过了

  set

<update id="update">
        update user
        <trim prefix="set" suffixOverrides=",">
            <if test="username!=null">
                username=#{username},
            </if>
            <if test="password!=null">
                password=#{password},
            </if>    
        </trim>
        where id=#{id}
</update>
<!--set原理与where很相似,set会自动处理语句后的逗号,如果语句以逗号结尾则会删掉逗号,以及会给语句前加上set关键字-->

  trim 

<!--prefix:前缀,在返回的字符串前添加什么内容
    suffix:后缀,在饭后的字符串后添加什么内容
    prefixOverrides:当字符串以什么内容开头时,该内容会被覆盖
    suffixOverrides:当字符串以什么内容结尾时,该内容会被覆盖
-->
<trim prefix="" suffix="" prefixOverrides="" suffixOverrides="">

</trim>


<!--trim模仿where-->
<trim prefix="where" prefixOverrides="and'></trim>
<!--trim模仿set-->
<trim prefix="set" suffixOverrides=","></trim>

  foreach

<!--collection:遍历元素的类型
  item:遍历时每次的变量名
  index:每次的下标(从0开始计数)
  open:字符串开头添加
  close:字符串结尾添加
  separator:元素之间的分隔符-->
<select id="selectPostIn" resultType="domain.blog.Post">
  SELECT *
  FROM POST P
  WHERE ID in
  <foreach item="item" index="index" collection="list"
      open="(" separator="," close=")">
        #{item}
  </foreach>
</select>

5、Sql语句中${}和#{}的区别  

  #{}:会吧参数的位置使用”?”做占位符,执行SQL的时候才会替换”?”的值

  ${}:直接把参数中的值作为SQL的一部分来执行 -----------> 可能会有SQL注入的问题

  如何选用?

    ${}:当插入的参数时作为SQL执行的一部分的时候必须使用${};

    #{}:当传入的参数时同数据库进行交互的时候,使用#{}.

  简单的判断:传入的参数在SQL中是否能够加上单引号 可以加单引号,使用#{},不能加单引号,使用${}

6、多参数问题处理

  解决方案: 把多个对象封装成一个对象

  1、封装成一个javaBean对象

  2、封装成一个Map对象  将属性名设为Map的key,属性值设为value

  3、使用@param注解

 

posted on 2019-09-01 21:34  幸福的小耗子  阅读(183)  评论(1编辑  收藏  举报