MyBaits | 映射文件之参数处理

一、MyBaits的增删改查

1. 介绍

输入映射

这里我先介绍一下输入映射,是在映射文件中通过 parameterType 指定输入参数的类型,类型可以是简单类型、HashmapPOJO 的包装类型。在实际操作中,一般我们会在 parameterType 属性中传入 POJO 的类名。如果是通过输入条件进行查询,我们只需要传入对应的 POJO 中的属性即可

输出映射

输出映射就是 sql 语句查询结束后返回的结果类型,在映射文件中通过 resultType 来显示输出的结果类型,不过一般可以不用设置 resultType,MyBatis 会自己帮我们输出。另外还可以使用 resultMap,这种配置方式可以用于各种复杂的映射方式,比如一对多,多对多等等,在后面的文章中会加以介绍

2. 使用 resultType 配置实现增删改查

①.首先我们定义一个 POJO 类:Employee.java

public class Employee {

    private Integer id;
    private String lastName;
    private String email;
    private Integer gender;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }
        ......
}


②. 然后我们定义一个接口类:EmployeeMapper.java,该接口包含了对 Employee 的增删改查操作

public interface EmployeeMapper {
        
    public void addEmployee(Employee employee);
    
    public void updateEmployee(Employee employee);
    
    public long deleteEmployee(Integer id);
    
    public Employee getEmployee(Integer id);
    
}


③. 配置 EmployeeMapper.xml,这里我就只对增加操作加以说明,其他三种操作与之类似

<mapper namespace="edu.just.mybatis.dao.EmployeeMapper">
    <select id="getEmployee" resultType="edu.just.mybatis.bean.Employee">
        select id, last_name lastName, email, gender from employee where id = #{id}
    </select>
</mapper>
  • namespace:指定为你要实现的接口的全类名
  • id:唯一标识 resultType: 返回值类型
  • parameterType:是传入的参数的类型,可以使用别名,如果返回的是一个集合, 则写集合中元素的类型,比如 Employee, mybaits 会自动帮你把该类的对象放入集合中并返回
  • resultType:返回查询结果的类型,没有指定别名的情况下,使用全类名,当然也可以省略

④. 写一个测试语句,使用接口定义的方法

@Test
public void testGetEmployee() throws IOException {
    //1. 获取 sqlSessionFactory 对象
    SqlSessionFactory sqlSessionFactory = getSqlSessionFactoty();
    
    //2. 获取 sqlSession 对象
    SqlSession sqlSession = sqlSessionFactory.openSession();
        
    try {
        //3. 获取接口的实现类对象, 会为接口自动创建一个代理对象, 代理对象去执行增、删、改、查
        EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
        Employee employee = employeeMapper.getEmployee(1);
        System.out.println(employee);
    } finally {
        sqlSession.close();
    }
}

这里需要注意的是:如果涉及到对数据库数据本身的操作,针对增删改,每次执行完 sql 语句都需要提交数据,如果只是查询操作,则可以不必提交

  1. 如果创建 openSession() 没有加参数,则在执行 sql 的语句后提交数据,可以使用 sqlSession.commit()
  2. 如果创建 openSession(true), 则不需要提交数据

3. 其他情况

3.1 获取自增主键的值

在配置文件中将 useGeneratedKeys 属性设置为 true,同时 keyProperty 属性指定将获取的主键值赋给 JavaBean 的哪个属性

<insert id="addEmployee" parameterType="Employee" useGeneratedKeys="true" keyProperty="id">
    Insert into employee(last_name, email, gender) values(#{lastName}, #{email}, #{gender})
</insert>

该配置表示将主键值赋给 Employee 的 id 属性,在测试文件中如果输出 id,即为当前查询结果的主键值

3.2 返回 List 集合的操作

首先在接口类中添加返回集合的方法

public List<Employee> getEmployees(String lastName);

然后在 sql 映射文件中配置,此时 resultType 的类型依旧是 Employee,因为对应的是集合中参数的类型

<select id="getEmployees" resultType="Employee">
    select * from employee where last_name like #{lastName}
</select>

输出如下

[Employee [id=7, lastName=null, email=lkj@123.com, gender=1], 
Employee [id=13, lastName=null, email=lkj@123.com, gender=2], 
Employee [id=14, lastName=null, email=lkj@123.com, gender=2], 
Employee [id=15, lastName=null, email=lkj@123.com, gender=2], 
Employee [id=16, lastName=null, email=lkj@123.com, gender=2]]


3.3 返回一个封装多个记录的 Map 集合

@MapKey() 告诉 mybatis 封装这个 map 时候使用哪个POJO 属性作为 key

@MapKey("id")
public Map<Integer, Employee> getEmployee3(Integer id);

配置 sql 映射文件,注意此时 resultType 类型依然是 Employee,即表示返回的类型依旧是 Employee

<select id="getEmployee3" resultType="Employee">
    select id, last_name lastName, email, gender from employee where id > #{id}
</select>

输出

{16=Employee [id=16, lastName=lkj, email=lkj@123.com, gender=2], 
17=Employee [id=17, lastName=lkj, email=lkj@123.com, gender=2], 
2=Employee [id=2, lastName=Peter, email=peter@qq.com, gender=1], 
19=Employee [id=19, lastName=lkj, email=lkj@123.com, gender=2], 
20=Employee [id=20, lastName=lkj, email=lkj@123.com, gender=2]}


二、对参数进行处理

1. 传入单个参数

传入单个参数时,${xxx} 里面的参数名和属性名无关,比如你占位符设置为 #{id},此时当然可以查询出结果。但是如果你设置为 #{id123},同样查询出结果, 但是如果什么都不填, 则会报错

<select id="getEmployee" resultType="edu.just.mybatis.bean.Employee">
       select id, last_name lastName, email, gender from employee where id = #{id123} 
</select>


2. 传入多个参数

我们先来看一个情景,如果需要传入 idlastName 两个参数

public Employee getEmployee2(Integer id, String lastName);

sql 的配置文件是这样设置的

<select id="getEmployee2" resultType="employee">
    select id, last_name lastName, email, gender from employee where 
      id = #{id} and last_name = #{lastName}
</select>

此时会出这样的错误:Cause: org.apache.ibatis.binding.BindingException: Parameter 'id' not found. Available parameters are [arg1, arg0, param1, param2]

原因就是当 sql 语句传入不止一个参数时, MyBatis 会做特殊处理, 多个参数会被封装到一个 Map 对象 map 中,当你每传入一个参数,map 对象会将参数以键为 param1, param2...paramN,值为你 传入的参数的值 的形式来保存数据,此时如果你传入的还是类似 #{id}#{name} 之类的参数,那么肯定会报错

解决方案

方案一
我们以上述的例子为例,我们可以直接传入 #{param1},#{param2} 等参数

<select id="getEmployee2" resultType="employee">
    select id, last_name lastName, email, gender from employee where 
        id = #{param1} and last_name = #{param2}
</select>

方案二
我们在接口定义的方法处,使用 @Param() 标注给方法中的参数起名字,其实本质上也是放在 Map 和对象 map 中

public Employee getEmployee2(@Param("id")Integer id, @Param("lastName")String lastName);

我们可以这样给传入的参数赋值,这时 map 中的 key 变为了 id, lastName, param1, param2。因此我们可以直接在 #{} 中传入我们自己命名的值。当然就算传入 #{param1} 之类的也是可以的。

<select id="getEmployee2" resultType="employee">
    select id, last_name lastName, email, gender from employee where 
        id = #{id} and last_name = #{lastName}
</select>


三、${} 和 #{} 的区别

#{}:是以预编译的形式,将参数设置到 sql 语句中,多用于 where 语句后面的填充位,
${}:取出的值直接拼接在 sql 语句中,多用于分表的 sql 语句,会有线程安全的问题

关于 #{} 的使用我不加以赘述,下面举例说明 ${} 用于分表的操作语句

select * from ${year}_table where xxx
select * from table order by ${xxx} ${xxx}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容