mybatis的xml的映射器-02

mybatis的xml映射器

MyBatis 的真正强大在于它的语句映射,这是它的魔力所在。由于它的异常强大,映射器的 XML 文件就显得相对简单。如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 95% 的代码。MyBatis 致力于减少使用成本,让用户能更专注于 SQL 代码。

xml的基本映射标签

1.select标签
mapper 接口中的方法:
/**
 * 查询所有
 */
List<User> selectList();

mapper xml的映射
<select id="selectList" resultType="cn.hk.bean.User">
        select * from t_user 
</select>

测试代码:

 @Test
 public void testSelectList(){

    // 获取SqlSession
    SqlSession sqlSession = SqlSessionUtils.getSqlSession();

    // 通过session获取Mapper接口
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);

    // 调用查询方法
    mapper.selectList();

    //关闭资源
    SqlSessionUtils.close(sqlSession);

}
2.insert 标签
mapper 接口中的方法:
/**
 * 查询所有
 */
List<User> selectList();

mapper xml的映射
<select id="selectList" resultType="cn.hk.bean.User">
        select * from t_user 
</select>

测试代码:

    @Test
    public void testInsert(){

        // 获取SqlSession
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();

        // 通过session获取Mapper接口
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        // 传入参数返回值

        User u = new User();
        u.setName("王语嫣");
        u.setPhone("1234");
        u.setPwd("abc");
        System.out.println(u);
        int i = mapper.insertUser(u);
        System.out.println(u);

        //提交事务
        sqlSession.commit();

        //关闭资源
        SqlSessionUtils.close(sqlSession);

    }

插入日志查看:
User{id=null, name='王语嫣', pwd='abc', phone='1234'}
DEBUG [main] - ==>  Preparing: insert into t_user(name ,pwd,phone) values(?,?,?) 
DEBUG [main] - ==> Parameters: 王语嫣(String), abc(String), 1234(String)
DEBUG [main] - <==    Updates: 1
User{id=6, name='王语嫣', pwd='abc', phone='1234'}

keyProperty="id" keyColumn="id" useGeneratedKeys="true" 配置了可以把 插入的数据的自增id
返回给对象
3.update 标签
mapper 接口中的方法:
  /**
  * 修改user
  */
 int updateUser(User u);

mapper xml的映射
<update id="updateUser" parameterType="cn.hk.bean.User">
    update  t_user set
        name = #{name},
        pwd = #{pwd},
        phone = #{phone}
    where id = #{id}
</update>

测试代码:

@Test
public void testUpdate(){

    // 获取SqlSession
    SqlSession sqlSession = SqlSessionUtils.getSqlSession();

    // 通过session获取Mapper接口
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);

    // 传入参数返回值

    User u = new User();
    u.setId(3);
    u.setName("周芷若");
    u.setPhone("1234");
    u.setPwd("abc");
    System.out.println(u);
    int i = mapper.updateUser(u);
    System.out.println(u);

    //提交事务
    sqlSession.commit();

    //关闭资源
    SqlSessionUtils.close(sqlSession);
}
4.delete标签
mapper 接口中的方法:
/**
 * 通过id删除
 */
int deleteUser(Integer id);

mapper xml的映射
<delete id="deleteUser">
    delete from t_user where id = #{id}
</delete>

测试代码:

    @Test
    public void testDelete(){

        // 获取SqlSession
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();

        // 通过session获取Mapper接口
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        // 传入参数返回值
        int i = mapper.deleteUser(2);
        System.out.println(i);

        //提交事务
        sqlSession.commit();

        //关闭资源
        SqlSessionUtils.close(sqlSession);
    }

5.注意事项
  1. 每个线程都应该有它自己的 SqlSession 实例。SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。 绝对不能将 SqlSession 实例的引用放在一个类的静态域,甚至一个类的实例变量也不行。 也绝不能将 SqlSession 实例的引用放在任何类型的托管作用域中

  2. mybatis的默认手动提交事务,进行更新操作(insert,update,delete) 操作后 一定要提交事务 commit()

6.参数
  1. 之前见到的所有语句都使用了简单的参数形式。但实际上,参数是 MyBatis 非常强大的元素。对于大多数简单的使用场景,你都不需要使用复杂的参数,比如:

  2. 一个参数

    <select id="selectUsers" resultType="User">
      select id, name, pwd
      from t_user
      where id = #{id}
    </select>
    

    上面的这个示例说明了一个非常简单的命名参数映射。鉴于参数类型(parameterType)会被自动设置为 int,这个参数可以随意命名。原始类型或简单数据类型(比如 IntegerString)因为没有其它属性,会用它们的值来作为参数。

    <insert id="insertUser" parameterType="User">
      insert into t_user (name, pwd,phone)
      values (#{name}, #{pwd}, #{phone})
    </insert>
    

    如果 User 类型的参数对象传递到了语句中,会查找 id、username 和 password 属性,然后将它们的值传入预处理语句的参数中。

    对传递语句参数来说,这种方式真是干脆利落。不过参数映射的功能远不止于此。

    和 MyBatis 的其它部分一样,参数也可以指定一个特殊的数据类型。

    #{id,javaType=int,jdbcType=NUMERIC}
    
    对于数值类型,还可以设置 numericScale 指定小数点后保留的位数。
    #{height,javaType=double,jdbcType=NUMERIC,numericScale=2}
    

    尽管上面这些选项很强大,但大多时候,你只须简单指定属性名,顶多要为可能为空的列指定 jdbcType,其他的事情交给 MyBatis 自己去推断就行了。

    #{name,jdbcType=VARCHAR}
    
7.字符串替换

默认情况下,使用 #{} 参数语法时,MyBatis 会创建 PreparedStatement 参数占位符,并通过占位符安全地设置参数(就像使用 ? 一样)。 这样做更安全,更迅速,通常也是首选做法,不过有时你就是想直接在 SQL 语句中直接插入一个不转义的字符串。

#{} 参数占位符

<select id="selectByName" parameterType="string" resultType="cn.hk.bean.User">
	select * from t_user where name = #{name}
</select>

测试日志:

DEBUG [main] - ==>  Preparing: select * from t_user where name = ?    //sql的占位符 
DEBUG [main] - ==> Parameters: 张三(String)
TRACE [main] - <==    Columns: id, name, pwd, phone
TRACE [main] - <==        Row: 1, 张三, 123456, 123456
DEBUG [main] - <==      Total: 1
User{id=1, name='张三', pwd='123456', phone='123456'}

${} 参数拼接

<select id="selectByName" parameterType="string" resultType="cn.hk.bean.User">
	select * from t_user where name = ${name}
</select>

测试代码:

public void testSelectName(){

    // 获取SqlSession
    SqlSession sqlSession = SqlSessionUtils.getSqlSession();

    // 通过session获取Mapper接口
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);

    // 传入参数返回值    参数设置注意加:''
    User user = mapper.selectByName("'张三'");

    System.out.println(user);

    //关闭资源
    SqlSessionUtils.close(sqlSession);
}

测试日志:

DEBUG [main] - ==>  Preparing: select * from t_user where name = '张三' 
// sql的字符串拼接
DEBUG [main] - ==> Parameters: 
TRACE [main] - <==    Columns: id, name, pwd, phone
TRACE [main] - <==        Row: 1, 张三, 123456, 123456
DEBUG [main] - <==      Total: 1
User{id=1, name='张三', pwd='123456', phone='123456'}

提示 ${} 用这种方式接受用户的输入,并用作语句参数是不安全的,会导致潜在的 SQL 注入攻击

8. 结果映射

resultMap 元素是 MyBatis 中最重要最强大的元素。它可以让你从 90% 的 JDBC ResultSets 数据提取代码中解放出来,并在一些情形下允许你进行一些 JDBC 不支持的操作。实际上,在为一些比如连接的复杂语句编写映射代码的时候,一份 resultMap 能够代替实现同等功能的数千行代码。ResultMap 的设计思想是,对简单的语句做到零配置,对于复杂一点的语句,只需要描述语句之间的关系就行了。

之前你已经见过简单映射语句的示例,它们没有显式指定 resultMap

在这些情况下,MyBatis 会在幕后自动创建一个 ResultMap,再根据属性名来映射列到 JavaBean 的属性上。如果列名和属性名不能匹配上会发生什么?

javaBean:

public class User {

    private Integer id;

    private String name;

    private String pwd;

    private String phone;
}

xml的映射:
<select id="selectByPrimaryKey" parameterType="integer" resultType="cn.hk.bean.User">
    select id u_id,name u_name,pwd u_password,phone u_phone from t_user where id = #{id}
</select>

类名和属性名不能匹配

测试结果:

@Test
public void testSelectOne(){

    // 获取SqlSession
    SqlSession sqlSession = SqlSessionUtils.getSqlSession();

    // 通过session获取Mapper接口
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);

    // 传入参数返回值
    User user = mapper.selectByPrimaryKey(4);

    System.out.println(user);

    //关闭资源
    SqlSessionUtils.close(sqlSession);
}

查看日志:

DEBUG [main] - ==>  Preparing: select id u_id,name u_name,pwd u_password,phone u_phone from t_user where id = ? 
DEBUG [main] - ==> Parameters: 4(Integer)
TRACE [main] - <==    Columns: u_id, u_name, u_password, u_phone
TRACE [main] - <==        Row: 4, 郭靖, aaa, 1234
DEBUG [main] - <==      Total: 1
null

Columns 和 resultType 不匹配 

使用resultMap是解决列名不匹配的一种方式

<!--
    resultMap 结果映射
    id	当前命名空间中的一个唯一标识,用于标识一个结果映射。
    type	类的完全限定名, 或者一个类型别名(关于内置的类型别名,可以参考上面的表格)。
    <id property="id" column="u_id"/>
    <result property="name" column="u_name"/>
    id 和 result 元素都将一个列的值映射到一个简单数据类型(String, int, double, Date 等)的属性或字段。
    id 元素对应的属性会被标记为对象的标识符

    property	映射到列结果的字段或属性。
    column	数据库中的列名,或者是列的别名(和传递给 resultSet.getString(columnName) 方法的参数一样。)
    javaType	一个 Java 类的全限定名,或一个类型别名
    jdbcType   JDBC 类型,所支持的 JDBC 类型参见这个表格之后的“支持的 JDBC 类型”。 
    注意类型 VARCHAR 大写 
-->
<resultMap id="rs_map" type="cn.hk.bean.User">
    <id property="id" column="u_id"/>
    <result property="name" javaType="string" column="u_name" jdbcType="VARCHAR"/>
    <result property="pwd" column="u_password"/>
    <result property="phone" column="u_phone"/>
</resultMap>

<select id="selectByPrimaryKey" parameterType="integer" resultMap="rs_map">
	select id u_id,name u_name,pwd u_password,phone u_phone from t_user where id = #{id}
</select>

测试代码:

    @Test
    public void testSelectOne(){

        // 获取SqlSession
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();

        // 通过session获取Mapper接口
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        // 传入参数返回值
        User user = mapper.selectByPrimaryKey(4);

        System.out.println(user);

        //关闭资源
        SqlSessionUtils.close(sqlSession);
    }

测试日志:

DEBUG [main] - ==>  Preparing: select id u_id,name u_name,pwd u_password,phone u_phone from t_user where id = ? 
DEBUG [main] - ==> Parameters: 4(Integer)
TRACE [main] - <==    Columns: u_id, u_name, u_password, u_phone
TRACE [main] - <==        Row: 4, 郭靖, aaa, 1234
DEBUG [main] - <==      Total: 1
User{id=4, name='郭靖', pwd='aaa', phone='1234'}

9 mybatis的注解开发:
映射器注解

设计初期的 MyBatis 是一个 XML 驱动的框架。配置信息是基于 XML 的,映射语句也是定义在 XML 中的。而在 MyBatis 3 中,我们提供了其它的配置方式。MyBatis 3 构建在全面且强大的基于 Java 语言的配置 API 之上。它是 XML 和注解配置的基础。注解提供了一种简单且低成本的方式来实现简单的映射语句。

提示 不幸的是,Java 注解的表达能力和灵活性十分有限。尽管我们花了很多时间在调查、设计和试验上,但最强大的 MyBatis 映射并不能用注解来构建——我们真没开玩笑。

常用的注解如下:

@Select 	查询数据注解
@Insert 	插入数据注解
@Delete 	删除数据注解
@Update 	修改数据注解
@Options 	选项配置
@Results 	手动映射配置

@Result:	@results中的具体的某一列的映射信息配置 
在列和属性或字段之间的单个结果映射。属性:id、column、javaType、jdbcType、typeHandler、one、many。id 属性和 XML 元素 <id> 相似,它是一个布尔值,表示该属性是否用于唯一标识和比较对象。one 属性是一个关联,和 <association> 类似,而 many 属性则是集合关联,和 <collection> 类似。这样命名是为了避免产生名称冲突。

注解的案例:

public interface UserMapperAnnotation {

 @Select(" select id u_id,name u_name,pwd u_password,phone u_phone from t_user where id = #{id}")
    @Results({
            @Result(id = true,property = "id",column = "u_id"),
            @Result(property = "name",column = "u_name"),
            @Result(property = "pwd",column = "u_password"),
            @Result(property = "phone",column = "u_phone"),
    })
    User selectByPrimaryKey(Integer id);

    @Select("select * from t_user")
    List<User> selectList();

    @Insert("insert into t_user(name,pwd,phone) values(#{name},#{pwd},#{phone})")
    @Options(
            keyProperty ="id",
            keyColumn = "id",
            useGeneratedKeys = true
    )
    int insertUser(User u);

    @Delete("delete from t_user where id = #{id}")
    int deleteUserById(Integer id);

    @Update("update t_user set name = #{name},pwd=#{pwd},phone = #{phone} where id = #{id}")
    int updateUser(User u);

}

注意: 需要在config中配置mapper接口:

<!--    配置mapper的映射-->
    <mappers>        
        <mapper class="cn.hk.mapper.UserMapperAnnotation"></mapper>
    </mappers>

测试代码:

package cn.hk.test;

import cn.hk.bean.User;
import cn.hk.mapper.UserMapperAnnotation;
import cn.hk.utils.SqlSessionUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.util.List;

/**
 * @author 黄药师
 * @date 2020-05-11 16:16
 * @desc
 */
public class UserAnnotationTest {

    @Test
    public void testSelectOne(){

        SqlSession sqlSession = SqlSessionUtils.getSqlSession();

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

        User user = mapper.selectByPrimaryKey(1);

        System.out.println(user);

        SqlSessionUtils.close(sqlSession);
    }

    @Test
    public void testSelectList(){

        SqlSession sqlSession = SqlSessionUtils.getSqlSession();

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

        List<User> users = mapper.selectList();

        System.out.println(users);

        SqlSessionUtils.close(sqlSession);
    }

    @Test
    public void testInsert(){

        SqlSession sqlSession = SqlSessionUtils.getSqlSession();

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


        User user = new User();

        user.setPhone("1111");
        user.setPwd("1234");
        user.setName("黄蓉");

        System.out.println(user);
        int i = mapper.insertUser(user);
        System.out.println(i);
        //提交事务
        sqlSession.commit();
        System.out.println(user);

        // 关闭资源
        SqlSessionUtils.close(sqlSession);
    }


    @Test
    public void testDelete(){

        SqlSession sqlSession = SqlSessionUtils.getSqlSession();

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

        int i = mapper.deleteUserById(3);
        System.out.println(i);
        //提交事务
        sqlSession.commit();
        // 关闭资源
        SqlSessionUtils.close(sqlSession);
    }

    @Test
    public void testUpdate(){

        SqlSession sqlSession = SqlSessionUtils.getSqlSession();

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

        User user = new User();

        user.setPhone("1111");
        user.setPwd("1234");
        user.setName("周伯通");
        user.setId(1);

        int i = mapper.updateUser(user);
        System.out.println(i);
        //提交事务
        sqlSession.commit();
        // 关闭资源
        SqlSessionUtils.close(sqlSession);
    }
}

10 多参数的处理

传递多个参数给一个映射器方法。在多个参数的情况下,默认它们将会以 param 加上它们在参数列表中的位置来命名,比如:#{param1}、#{param2}等。如果你想(在有多个参数时)自定义参数的名称,那么你可以在参数上使用 @Param(“paramName”) 注解。

如果你的映射方法接受多个参数,就可以使用这个注解自定义每个参数的名字。否则在默认情况下,除 RowBounds 以外的参数会以 “param” 加参数位置被命名。例如 #{param1}, #{param2}。如果使用了 @Param("person"),参数就会被命名为 #{person}

  1. 多个参数的使用

    不使用注解的多参数xml映射:
        /**
         *  查询 多个参数
         * @return
         */
     User selectUser(String name,String pwd);
       
       
     <select id="selectUser" resultType="cn.hk.bean.User">
         select * from t_user where name = #{param1} and pwd = #{param2}
     </select>
     
    
    使用注解的多参数设置:
    User selectUser01(@Param("username") String name,@Param("password") String pwd);  
    
    <select id="selectUser01" resultType="cn.hk.bean.User">
    	select * from t_user where name = #{username} and pwd = #{password}
    </select>
    
  2. 把多个参数封装成一个map

    User selectUser02(Map<String,Object> map);
    
    <!--
       #{map的key的名称}
    -->
    <select id="selectUser02" parameterType="map" resultType="cn.hk.bean.User">
        select * from t_user where name = #{name} and pwd = #{pwd}
    </select>
    

    测试代码:

        @Test
        public void testSelectUser02(){
    
            SqlSession sqlSession = SqlSessionUtils.getSqlSession();
    
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    
            HashMap<String, Object> map = new HashMap<>();
    
            map.put("name","王语嫣");
            map.put("pwd","abc");
    
            User user = mapper.selectUser02(map);
            System.out.println(user);
    
        }
    
  3. 把多个参数封装成对象

    User selectUser03(User user);
    
    <!--
    #{bean的属性的名称}
    -->
    <select id="selectUser03" parameterType="cn.hk.bean.User" resultType="cn.hk.bean.User">
        select * from t_user where name = #{name} and pwd = #{pwd}
    </select>
    
    

    测试代码:

        @Test
        public void testSelectUser03(){
    
            SqlSession sqlSession = SqlSessionUtils.getSqlSession();
    
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    
            User user = new User();
    
            user.setName("王语嫣");
            user.setPwd("abc");
    
            User u = mapper.selectUser03(user);
            System.out.println(u);
    
            SqlSessionUtils.close(sqlSession);
    
        }
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值