1. mybatis支持的映射方式

mybatis支持的映射方式有基于xml的mapper.xml文件、基于java的使用Mapper接口class,简单学习一下mybatis使用接口来配置映射的方法。

接口方法注解主要是四个:@Insert、@Delete、@Update、@Select

2. 如何使用接口注解来映射

下面的实验都是基于t_user表的,其结构如下:

DROP TABLE IF EXISTS t_user;
CREATE TABLE t_user (
id BIGINT AUTO_INCREMENT PRIMARY KEY ,
username VARCHAR(100) NOT NULL ,
passwd CHAR(32) NOT NULL,
birth_day DATETIME
) CHARSET UTF8;

2.1 增 @Insert

插入记录的时候麻烦的一点是主键如何生成,对此基本上有三种方案,分别是手动指定(应用层)、自增主键(数据层单表)、选择主键(数据层多表)。

1. 在应用层手动指定主键

手动指定的方式不把主键区别看待,插入之前在应用层生成对象的时候就会给主键一个值,插入的时候与普通字段没啥区别。

    /**
* 插入记录,手动分配主键
*
* @param user
* @return
*/
@Insert("INSERT INTO t_user (id, username, passwd) VALUES (#{id}, #{username}, #{passwd})")
int addUserAssignKey(User user);

在上面的这个例子中,mybatis并不知道到底哪个字段是主键,id虽然是主键字段,但并没有被区别对待。

注意#{username}这种写法,是把User作为了当前上下文,这样访问User的属性的时候直接写属性名字就可以了。

2. 表自增主键

自增主键对应着XML配置中的主键回填,一个简单的例子:

    /**
* 插入记录,数据库生成主键
*
* @param user
* @return
*/
@Options(useGeneratedKeys = true, keyProperty = "id")
@Insert("INSERT INTO t_user (username, passwd) VALUES (#{username}, #{passwd})")
int addUserGeneratedKey(User user);

使用Option来对应着XML设置的select标签的属性,userGeneratordKeys表示要使用自增主键,keyProperty用来指定主键字段的字段名。

自增主键会使用数据库底层的自增特性。

3. 选择主键

选择主键从数据层生成一个值,并用这个值作为主键的值。

    /**
* 插入记录,选择主键
*
* @param user
* @return
*/
@Insert("INSERT INTO t_user (username, passwd) VALUES (#{username}, #{passwd})")
@SelectKey(statement = "SELECT UNIX_TIMESTAMP(NOW())", keyColumn = "id", keyProperty = "id", resultType = Long.class, before = true)
int addUserSelectKey(User user);

2.2 删 @Delete

删除的时候只要把语句条件神马的写在@Delete注解的value里就好了,返回一个int类型是被成功删除的记录数。

    /**
* 删除记录
*
* @param id
* @return
*/
@Delete("DELETE FROM t_user WHERE id=#{id}")
int delete(Long id);

2.3 改 @Update

修改的时候和删除一样只要把SQL语句写在@Update的value中就好了,返回一个int类型表示被修改的记录行数。

    /**
* 修改记录
*
* @param user
* @return
*/
@Update("UPDATE t_user SET username=#{username}, passwd=#{passwd} WHERE id=#{id}")
int update(User user);

2.4 查 @Select

查询的时候稍稍有些复杂,因为查询会涉及到如何将查出来的字段设置到对象上,通常有那么三种办法:

1. 在SQL语句中手动指定别名来匹配

在写SQL语句的时候,手动为每一个字段指定一个别名来跟对象的属性做匹配,适用于表字段名与对象属性名差异很大没有规律并且表字段不多的情况。

    /**
* 根据ID查询,手动设置别名
*
* @param id
* @return
*/
@Select("SELECT id, username, passwd, birth_day AS birthDay FROM t_user WHERE id=#{id}")
User loadByIdHandAlias(Long id);

2. 使用mybatis的自动下划线驼峰转换

mybatis有一个选项叫mapUnderscoreToCamelCase,当表中的字段名与对象的属性名相同只是下划线和驼峰写法的差异时适用。

配置了mapUnderscoreToCamelCase之后mybatis在将ResultSet查出的数据设置到对象的时候会尝试先将下划线转换为驼峰然后前面拼接set去设置属性。

开启转换:

然后查询:

    /**
* 根据ID查询,开了自动驼峰转换
*
* @param id
* @return
*/
@Select("SELECT * FROM t_user WHERE id=#{id}")
User loadByIdAutoAlias(Long id);

查看打印的结果,birth_day属性填充到了对象中:

3. 使用ResultMap

对于表的字段名和对象的属性名没有太大相同点并且表中的字段挺多的情况下,应该使用ResultMap做适配。

    /**
* 使用ResultMap
*
* @param id
* @return
*/
@Results(id = "userMap", value = {
@Result(id=true, column = "id", property = "id"),
@Result(column = "username", property = "username"),
@Result(column = "passwd", property = "passwd"),
@Result(column = "birth_day", property = "birthDay")
})
@Select("SELECT * FROM t_user WHERE id=#{id}")
User loadByIdResultMap(Long id);

@Results对应着XML中的ResultMap,同时可以为其指定一个id,其它地方可以使用这个id来引用它,比如要引用上面的这个Results:

    /**
* 引用其他的Result
*
* @param id
* @return
*/
@ResultMap("userMap")
@Select("SELECT * FROM t_user WHERE id=#{id}")
User loadByIdResultMapReference(Long id);

使用@ResultMap来引用一个已经存在的ResultMap,这个ResultMap可以是在Java中使用@Results注解定义的,也可以是在XML中使用resultMap标签定义的。

2.5 样例代码

User.java

package org.cc11001100.mybatis.domain;

import org.apache.ibatis.type.Alias;

import java.util.Date;

/**
* @author: CC11001100
* @date: 2017/11/9 18:33
* @email: CC11001100@qq.com
*/
@Alias("user")
public class User { private Long id; private String username; private String passwd; private Date birthDay; public User() {
} public User(String username, String passwd) {
this.username = username;
this.passwd = passwd;
} public User(Long id, String username, String passwd) {
this.id = id;
this.username = username;
this.passwd = passwd;
} public Date getBirthDay() {
return birthDay;
} public void setBirthDay(Date birthDay) {
this.birthDay = birthDay;
} public Long getId() {
return id;
} public void setId(Long id) {
this.id = id;
} public String getUsername() {
return username;
} public void setUsername(String username) {
this.username = username;
} public String getPasswd() {
return passwd;
} public void setPasswd(String passwd) {
this.passwd = passwd;
} @Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", passwd='" + passwd + '\'' +
", birthDay=" + birthDay +
'}';
}
}

UserMapper.java

package org.cc11001100.mybatis.mapper;

import org.apache.ibatis.annotations.*;
import org.cc11001100.mybatis.domain.User;
import org.springframework.stereotype.Repository; /**
* @author: CC11001100
* @date: 2017/11/9 18:16
* @email: CC11001100@qq.com
*/
@Mapper
@Repository
public interface UserMapper { /**
* 插入记录,手动分配主键
*
* @param user
* @return
*/
@Insert("INSERT INTO t_user (id, username, passwd) VALUES (#{id}, #{username}, #{passwd})")
int addUserAssignKey(User user); /**
* 插入记录,数据库生成主键
*
* @param user
* @return
*/
@Options(useGeneratedKeys = true, keyProperty = "id")
@Insert("INSERT INTO t_user (username, passwd) VALUES (#{username}, #{passwd})")
int addUserGeneratedKey(User user); /**
* 插入记录,选择主键
*
* @param user
* @return
*/
@Insert("INSERT INTO t_user (username, passwd) VALUES (#{username}, #{passwd})")
@SelectKey(statement = "SELECT UNIX_TIMESTAMP(NOW())", keyColumn = "id", keyProperty = "id", resultType = Long.class, before = true)
int addUserSelectKey(User user); /**
* 删除记录
*
* @param id
* @return
*/
@Delete("DELETE FROM t_user WHERE id=#{id}")
int delete(Long id); /**
* 修改记录
*
* @param user
* @return
*/
@Update("UPDATE t_user SET username=#{username}, passwd=#{passwd} WHERE id=#{id}")
int update(User user); /**
* 根据ID查询,手动设置别名
*
* @param id
* @return
*/
@Select("SELECT id, username, passwd, birth_day AS birthDay FROM t_user WHERE id=#{id}")
User loadByIdHandAlias(Long id); /**
* 根据ID查询,开了自动驼峰转换
*
* @param id
* @return
*/
@Select("SELECT * FROM t_user WHERE id=#{id}")
User loadByIdAutoAlias(Long id); /**
* 使用ResultMap
*
* @param id
* @return
*/
@Results(id = "userMap", value = {
@Result(id=true, column = "id", property = "id"),
@Result(column = "username", property = "username"),
@Result(column = "passwd", property = "passwd"),
@Result(column = "birth_day", property = "birthDay")
})
@Select("SELECT * FROM t_user WHERE id=#{id}")
User loadByIdResultMap(Long id); /**
* 引用其他的Result
*
* @param id
* @return
*/
@ResultMap("userMap")
@Select("SELECT * FROM t_user WHERE id=#{id}")
User loadByIdResultMapReference(Long id); }

3. 总结

使用接口注解的优点:

  1. 比较方便,快速编写映射语句

使用接口注解的缺点:

  1. 适用于比较简单的配置,当太复杂了接口就搞不定了。

2. 不能使用动态SQL,有点鸡肋。

mybatis笔记之使用Mapper接口注解的更多相关文章

  1. Mybatis MapperScannerConfigurer 自动扫描 将Mapper接口生成代理注入到Spring - 大新博客 - 推酷 - 360安全浏览器 7.1

    Mybatis MapperScannerConfigurer 自动扫描 将Mapper接口生成代理注入到Spring - 大新博客 时间 2014-02-11 21:08:00  博客园-所有随笔区 ...

  2. Mybatis MapperScannerConfigurer 自动扫描 将Mapper接口生成代理注入到Spring

    Mybatis MapperScannerConfigurer 自动扫描 将Mapper接口生成代理注入到Spring 非原创[只为记录],原博文地址:https://www.cnblogs.com/ ...

  3. (转)Mybatis MapperScannerConfigurer 自动扫描 将Mapper接口生成代理注入到Spring

    Mybatis MapperScannerConfigurer 自动扫描 将Mapper接口生成代理注入到Spring Mybatis在与Spring集成的时候可以配置MapperFactoryBea ...

  4. 加载映射文件几种方式和mapper接口注解执行sql语句

    一.加载映射文件几种方式 二.mapper接口注解执行sql语句 就将xml中的sql语句放到注解的括号中就可以,一般只用于简单的sql语句合适:

  5. Spring Boot 整合mybatis时遇到的mapper接口不能注入的问题

    现实情况是这样的,因为在练习spring boot整合mybatis,所以自己新建了个项目做测试,可是在idea里面mapper接口注入报错,后来百度查询了下,把idea的注入等级设置为了warnin ...

  6. spring与mybatis整合(扫描Mapper接口)

    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean" ...

  7. Mybatis是如何将Mapper接口注册到Spring IoC的

    1. 前言 有时候我们需要自行定义一些注解来标记某些特定功能的类并将它们注入Spring IoC容器.比较有代表性的就是Mybatis的Mapper接口.假如有一个新的需求让你也实现类似的功能你该如何 ...

  8. 【eclipse】mybatis配置文件创建与mapper接口文件创建

    什么是mybatis: MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射. mybatis配置文件: <?xml version="1.0" ...

  9. mybatis入门篇:Mapper接口/关联查询/新增数据

    1.数据准备 2.编写实体类 package com.forest.owl.entity; import java.util.Date; public class User { private Lon ...

随机推荐

  1. Geek荣耀大会总结

    0.0 首先没有被抽中, 其次可乐真难喝,再次我没有去拍无人机合影,再再次还是很受打击的. 1.0 其实 对geek 和1024大会无感,主要原因 没有三倍加班费的节日在我眼里都不是节日. 上面只是简 ...

  2. VSVC2010中常用的C++11特性

    static_assert 声明 static_assert 声明在编译时测试软件断言,这与在运行时进行测试的其他断言机制不同. 如果断言失败,则编译也将失败,且系统将发出指定的错误消息. const ...

  3. idea tomcat debug 失效

    idea 开发神器 有时候遇到各种问题 这不 现在遇到了一个问题 启动容器时 debug断点不能进入 在网上找了老半天 终于找到答案了 原因是使用tomcat的时候 没有选择"pass en ...

  4. 如何在VScode中添加代码片段

    拿 VUE 举例,新建 VUE 文件,输入前缀,出现代码段 文件 --->  首选项 ---> 用户代码片段  在输入框中输入 vue ,找到 vue.json ,然后在 vue.json ...

  5. python 序列化 pickle shelve json configparser

    1. 什么是序列化 我们把变量从内存中变成可存储或传输的过程称之为序列化. 序列化之后,就可以把序列化后的内容写入磁盘,或者通过网络传输到别的机器上. 反过来,把变量内容从序列化的对象重新读到内存里称 ...

  6. 【刷题】BZOJ 3365 [Usaco2004 Feb]Distance Statistics 路程统计

    Description 在得知了自己农场的完整地图后(地图形式如前三题所述),约翰又有了新的问题.他提供 一个整数K(1≤K≤109),希望你输出有多少对农场之间的距离是不超过K的. Input 第1 ...

  7. [TJOI2015]线性代数 网络流

    题面 题面 题解 先化一波式子: \[D = (A \cdot B - C)A^T \] \[ = \sum_{i = 1}^{n}H_{1i}\cdot A^T_{i1}\] \[H_{1i} = ...

  8. 【Revit API】Revit读取当前rvt的所有视图与其名称

    1)读取所有视图: public static ViewSet GetAllViews(Document doc) { ViewSet views = new ViewSet(); FilteredE ...

  9. 【BZOJ2876】【NOI2012】骑行川藏(数学,二分答案)

    [BZOJ2876][NOI2012]骑行川藏(数学,二分答案) 题面 BZOJ 题解 我们有一个很有趣的思路. 首先我们给每条边随意的赋一个初值. 当然了,这个初值不会比这条边的风速小. 那么,我们 ...

  10. skip-external-locking --mysql配置说明

    MySQL的配置文件my.cnf中默认存在一行skip-external-locking的参数,即“跳过外部锁定”.根据MySQL开发网站的官方解释,External-locking用于多进程条件下为 ...