MyBatis基本使用

1 MyBatis基本使用

1.1 mybatis日志输出配置

    <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

1.2 mybatis取值符号#和$的区别

Mybatis会将SQL语句中的#{}转换为问号占位符。

${}形式传参,底层Mybatis做的是字符串拼接操作。

通常不会采用${}的方式传值。一个特定的适用场景是:通过Java程序动态生成数据库表,表名部分需要Java程序通过参数传入;而JDBC对于表名部分是不能使用问号占位符的,此时只能使用

结论:实际开发中,能用#{}实现的,肯定不用${}。

特殊情况: 动态的不是值,是列名或者关键字,需要使用${}拼接

2 数据输入

2.1 单个简单类型传入

Mapper接口中抽象方法的声明

Employee selectEmployee(Integer empId);

SQL语句

单个简单类型参数,在#{}中可以随意命名,但是没有必要。通常还是使用和接口方法参数同名。

<select id="selectEmployee" resultType="com.lx.pojo.Employee">
  select emp_id empId,emp_name empName,emp_salary empSalary from t_emp where emp_id=#{empId}
</select>

2.2 单个实体类类型传入

Mapper接口中抽象方法的声明

int insertEmployee(Employee employee);

SQL语句

Mybatis会根据#{}中传入的数据,加工成getXxx()方法,通过反射在实体类对象中调用这个方法,从而获取到对应的数据。填充到#{}解析后的问号占位符这个位置。基本等同于实体类中的属性名

<insert id="insertEmployee">
  insert into t_emp(emp_name,emp_salary) values(#{empName},#{empSalary})
</insert>

2.3 多个简单类型传入

零散的多个简单类型参数,如果没有特殊处理,那么Mybatis无法识别自定义名称,使用@Param()指定名称

Mapper接口中抽象方法的声明

int updateEmployee(@Param("empId") Integer empId,@Param("empSalary") Double empSalary);

SQL语句

<!-- 方式一:使用@Param指定参数名称-->
<update id="updateEmployee">
  update t_emp set emp_salary=#{empSalary} where emp_id=#{empId}
</update>

<!-- 方式二:使用mybatis默认机制 不用@Param指定参数名称-->
<!--    arg0 aro1 ... 形参从左到右一一对应参数顺序-->
<update id="updateEmployee">
  update t_emp set emp_id=#{arg0} where emp_salary=#{arg1}
</update>
<!--    param1 param2 形参从左到右一一对应参数顺序-->
<update id="updateEmployee">
  update t_emp set emp_id=#{param1} where emp_salary=#{param2}
</update>

2.4 map类型传入

有很多零散的参数需要传递,但是没有对应的实体类类型可以使用。使用@Param注解一个一个传入又太麻烦了。所以都封装到Map中。
Mapper接口中抽象方法的声明

int updateEmployeeByMap(Map<String, Object> paramMap);

#{}中写Map中的key

SQL语句

<update id="updateEmployeeByMap">

  update t_emp set emp_salary=#{empSalaryKey} where emp_id=#{empIdKey}

</update>

junit测试

。。。。
  paramMap.put("empSalaryKey", 999.99);
  paramMap.put("empIdKey", 5);
。。。。

3 数据输出

3.1 输出概述

数据输出总体上有两种形式:

  • 增删改操作返回的受影响行数:直接使用 int 或 long 类型接收即可
  • 查询操作的查询结果

我们需要做的是,指定查询的输出数据类型即可!

并且插入场景下,实现主键数据回显示!

3.2 单个简单类型输出

Mapper接口中的抽象方法

int selectEmpCount();

SQL语句

<select id="selectEmpCount" resultType="int">
  select count(*) from t_emp
</select>

Mybatis 内部给常用的数据类型设定了很多别名。 以 int 类型为例,可以写的名称有:int、integer、Integer、java.lang.Integer、Int、INT、INTEGER 等等。

junit测试

@Test

public void testEmpCount() {

  EmployeeMapper employeeMapper = session.getMapper(EmployeeMapper.class);

  int count = employeeMapper.selectEmpCount();

  log.info("count = " + count);

}

细节解释:

select标签,通过resultType指定查询返回值类型!

resultType = “全限定符 | 别名 | 如果是返回集合类型,写范型类型即可”

别名问题:

https://mybatis.org/mybatis-3/zh/configuration.html#typeAliases

类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。例如:

<typeAliases>
  <typeAlias alias="Author" type="domain.blog.Author"/>
  <typeAlias alias="Blog" type="domain.blog.Blog"/>
</typeAliases>

当这样配置时,Blog 可以用在任何使用 domain.blog.Blog 的地方。

也可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean,比如:

<typeAliases> <package name="domain.blog"/> </typeAliases>

每一个在包 domain.blog 中的 Java Bean,在没有注解的情况下,会使用 Bean 的首字母小写的非限定类名来作为它的别名。 比如 domain.blog.Author 的别名为 author;若有注解,则别名为其注解值。见下面的例子:

@Alias("author")
public class Author {
    ...
}

下面是Mybatis为常见的 Java 类型内建的类型别名。它们都是不区分大小写的,注意,为了应对原始类型的命名重复,采取了特殊的命名风格。

别名映射的类型
_bytebyte
_char (since 3.5.10)char
_character (since 3.5.10)char
_longlong
_shortshort
_intint
_integerint
_doubledouble
_floatfloat
_booleanboolean
stringString
byteByte
char (since 3.5.10)Character
character (since 3.5.10)Character
longLong
shortShort
intInteger
integerInteger
doubleDouble
floatFloat
booleanBoolean
dateDate
decimalBigDecimal
bigdecimalBigDecimal
bigintegerBigInteger
objectObject
object[]Object[]
mapMap
hashmapHashMap
listList
arraylistArrayList
collectionCollection

3.3 单个实体类对象输出

Mapper接口的抽象方法

Employee selectEmployee(Integer empId);

SQL语句

<!-- 编写具体的SQL语句,使用id属性唯一的标记一条SQL语句 -->
<!-- resultType属性:指定封装查询结果的Java实体类的全类名 -->
<select id="selectEmployee" resultType="com.lx.mybatis.entity.Employee">

  <!-- Mybatis负责把SQL语句中的#{}部分替换成“?”占位符 -->
  <!-- 给每一个字段设置一个别名,让别名和Java实体类中属性名一致 -->
  select emp_id empId,emp_name empName,emp_salary empSalary from t_emp where emp_id=#{maomi}

</select>

通过给数据库表字段加别名,让查询结果的每一列都和Java实体类中属性对应起来。

增加全局配置自动识别对应关系

在 Mybatis 全局配置文件中,做了下面的配置,select语句中可以不给字段设置别名

<!-- 在全局范围内对Mybatis进行配置 -->
<settings>

  <!-- 具体配置 -->
  <!-- 从org.apache.ibatis.session.Configuration类中可以查看能使用的配置项 -->
  <!-- 将mapUnderscoreToCamelCase属性配置为true,表示开启自动映射驼峰式命名规则 -->
  <!-- 规则要求数据库表字段命名方式:单词_单词 -->
  <!-- 规则要求Java实体类属性名命名方式:首字母小写的驼峰式命名 -->
  <setting name="mapUnderscoreToCamelCase" value="true"/>

</settings>

3.4 返回Map类型

适用于SQL查询返回的各个字段综合起来并不和任何一个现有的实体类对应,没法封装到实体类对象中。能够封装成实体类类型的,就不使用Map类型。

Mapper接口的抽象方法

Map<String,Object> selectEmpNameAndMaxSalary();

SQL语句

<!-- Map<String,Object> selectEmpNameAndMaxSalary(); -->
<!-- 返回工资最高的员工的姓名和他的工资 -->
<select id="selectEmpNameAndMaxSalary" resultType="map">
  SELECT
    emp_name 员工姓名,
    emp_salary 员工工资,
    (SELECT AVG(emp_salary) FROM t_emp) 部门平均工资
  FROM t_emp WHERE emp_salary=(
    SELECT MAX(emp_salary) FROM t_emp
  )
</select>

junit测试

@Test
public void testQueryEmpNameAndSalary() {

  EmployeeMapper employeeMapper = session.getMapper(EmployeeMapper.class);

  Map<String, Object> resultMap = employeeMapper.selectEmpNameAndMaxSalary();

  Set<Map.Entry<String, Object>> entrySet = resultMap.entrySet();

  for (Map.Entry<String, Object> entry : entrySet) {

    String key = entry.getKey();

    Object value = entry.getValue();

    log.info(key + "=" + value);

  }
}

3.5 返回List类型

查询结果返回多个实体类对象,希望把多个实体类对象放在List集合中返回。此时不需要任何特殊处理,在resultType属性中还是设置实体类类型即可。返回值类型是List集合中的泛型。

Mapper接口中抽象方法

List<Employee> selectAll();

SQL语句

<!-- List<Employee> selectAll(); -->
<select id="selectAll" resultType="com.lx.mybatis.entity.Employee">
  select emp_id empId,emp_name empName,emp_salary empSalary
  from t_emp
</select>

junit测试

@Test
public void testSelectAll() {
  EmployeeMapper employeeMapper = session.getMapper(EmployeeMapper.class);
  List<Employee> employeeList = employeeMapper.selectAll();
  for (Employee employee : employeeList) {
    log.info("employee = " + employee);
  }
}

3.6 返回主键值

3.6.1 自增长类型主键

Mapper接口中的抽象方法

   int insertEmployee(Employee employee);

SQL语句

   <!-- int insertEmployee(Employee employee); -->
   <!-- useGeneratedKeys属性字面意思就是“使用生成的主键” -->
   <!-- keyProperty属性可以指定主键在实体类对象中对应的属性名,Mybatis会将拿到的主键值存入这个属性 -->
   <insert id="insertEmployee" useGeneratedKeys="true" keyProperty="empId">
     insert into t_emp(emp_name,emp_salary)
     values(#{empName},#{empSalary})
   </insert>

junit测试

   @Test
   public void testSaveEmp() {
     EmployeeMapper employeeMapper = session.getMapper(EmployeeMapper.class);
     Employee employee = new Employee();
     employee.setEmpName("john");
     employee.setEmpSalary(666.66);
     employeeMapper.insertEmployee(employee);
     log.info("employee.getEmpId() = " + employee.getEmpId());
   }

注意

Mybatis是将自增主键的值设置到实体类对象中,而不是以Mapper接口方法返回值的形式返回。

3.6.2 非自增长类型主键

而对于不支持自增型主键的数据库(例如 Oracle)或者字符串类型主键,则可以使用 selectKey 子元素:selectKey 元素将会首先运行,id 会被设置,然后插入语句会被调用!

使用 selectKey 帮助插入UUID作为字符串类型主键示例:

<insert id="insertUser" parameterType="User">
    <selectKey keyProperty="id" resultType="java.lang.String"
        order="BEFORE">
        SELECT UUID() as id
    </selectKey>
    INSERT INTO user (id, username, password) 
    VALUES (
        #{id},
        #{username},
        #{password}
    )
</insert>

在上例中,我们定义了一个 insertUser 的插入语句来将 User 对象插入到 user 表中。我们使用 selectKey 来查询 UUID 并设置到 id 字段中。

通过 keyProperty 属性来指定查询到的 UUID 赋值给对象中的 id 属性,而 resultType 属性指定了 UUID 的类型为 java.lang.String

需要注意的是,我们将 selectKey 放在了插入语句的前面,这是因为 MySQL 在 insert 语句中只支持一个 select 子句,而 selectKey 中查询 UUID 的语句就是一个 select 子句,因此我们需要将其放在前面。

最后,在将 User 对象插入到 user 表中时,我们直接使用对象中的 id 属性来插入主键值。

使用这种方式,我们可以方便地插入 UUID 作为字符串类型主键。当然,还有其他插入方式可以使用,如使用Java代码生成UUID并在类中显式设置值等。需要根据具体应用场景和需求选择合适的插入方式。

3.7 实体类属性和数据库字段对应关系

3.7.1 别名对应

将字段的别名设置成和实体类属性一致。

   <!-- 编写具体的SQL语句,使用id属性唯一的标记一条SQL语句 -->
   <!-- resultType属性:指定封装查询结果的Java实体类的全类名 -->
   <select id="selectEmployee" resultType="com.lx.mybatis.entity.Employee">
   
     <!-- Mybatis负责把SQL语句中的#{}部分替换成“?”占位符 -->
     <!-- 给每一个字段设置一个别名,让别名和Java实体类中属性名一致 -->
     select emp_id empId,emp_name empName,emp_salary empSalary from t_emp where emp_id=#{maomi}
   
   </select>

关于实体类属性的约定:
getXxx()方法、setXxx()方法把方法名中的get或set去掉,首字母小写。

3.7.2 全局配置自动识别驼峰式命名规则

在Mybatis全局配置文件加入如下配置:

   <!-- 使用settings对Mybatis全局进行设置 -->
   <settings>
   
     <!-- 将xxx_xxx这样的列名自动映射到xxXxx这样驼峰式命名的属性名 -->
     <setting name="mapUnderscoreToCamelCase" value="true"/>
   
   </settings>

SQL语句中可以不使用别名

   <!-- Employee selectEmployee(Integer empId); -->
   <select id="selectEmployee" resultType="com.atguigu.mybatis.entity.Employee">
   
     select emp_id,emp_name,emp_salary from t_emp where emp_id=#{empId}
   
   </select>

3.7.3 使用resultMap

使用resultMap标签定义对应关系,再在后面的SQL语句中引用这个对应关系

   <!-- 专门声明一个resultMap设定column到property之间的对应关系 -->
   <resultMap id="selectEmployeeByRMResultMap" type="com.lx.mybatis.entity.Employee">
   
     <!-- 使用id标签设置主键列和主键属性之间的对应关系 -->
     <!-- column属性用于指定字段名;property属性用于指定Java实体类属性名 -->
     <id column="emp_id" property="empId"/>
   
     <!-- 使用result标签设置普通字段和Java实体类属性之间的关系 -->
     <result column="emp_name" property="empName"/>
   
     <result column="emp_salary" property="empSalary"/>
   
   </resultMap>
   
   <!-- Employee selectEmployeeByRM(Integer empId); -->
   <select id="selectEmployeeByRM" resultMap="selectEmployeeByRMResultMap">
   
     select emp_id,emp_name,emp_salary from t_emp where emp_id=#{empId}
   
   </select>

4 mapperXML标签总结

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

SQL 映射文件只有很少的几个顶级元素(按照应被定义的顺序列出):

  • insert – 映射插入语句。
  • update – 映射更新语句。
  • delete – 映射删除语句。
  • select – 映射查询语句。

4.1 select标签

MyBatis 在查询和结果映射做了相当多的改进。一个简单查询的 select 元素是非常简单:

<select id="selectPerson" 
resultType="hashmap" resultMap="自定义结构"> SELECT * FROM PERSON WHERE ID = #{id} </select>

这个语句名为 selectPerson,接受一个 int(或 Integer)类型的参数,并返回一个 HashMap 类型的对象,其中的键是列名,值便是结果行中的对应值。

注意参数符号:#{id} ${key}

MyBatis 创建一个预处理语句(PreparedStatement)参数,在 JDBC 中,这样的一个参数在 SQL 中会由一个“?”来标识,并被传递到一个新的预处理语句中,就像这样:

// 近似的 JDBC 代码,非 MyBatis 代码...
String selectPerson = "SELECT * FROM PERSON WHERE ID=?";
PreparedStatement ps = conn.prepareStatement(selectPerson);
ps.setInt(1,id);

select 元素允许你配置很多属性来配置每条语句的行为细节:

属性描述
id在命名空间中唯一的标识符,可以被用来引用这条语句。
resultType期望从这条语句中返回结果的类全限定名或别名。 注意,如果返回的是集合,那应该设置为集合包含的类型,而不是集合本身的类型。 resultType 和 resultMap 之间只能同时使用一个。
resultMap对外部 resultMap 的命名引用。结果映射是 MyBatis 最强大的特性,如果你对其理解透彻,许多复杂的映射问题都能迎刃而解。 resultType 和 resultMap 之间只能同时使用一个。
timeout这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为未设置(unset)(依赖数据库驱动)。
statementType可选 STATEMENT,PREPARED 或 CALLABLE。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED。

4.2 insert, update 和 delete标签

数据变更语句 insert,update 和 delete 的实现非常接近:

<insert
  id="insertAuthor"
  statementType="PREPARED"
  keyProperty=""
  keyColumn=""
  useGeneratedKeys=""
  timeout="20">

<update
  id="updateAuthor"
  statementType="PREPARED"
  timeout="20">

<delete
  id="deleteAuthor"
  statementType="PREPARED"
  timeout="20">
属性描述
id在命名空间中唯一的标识符,可以被用来引用这条语句。
timeout这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为未设置(unset)(依赖数据库驱动)。
statementType可选 STATEMENT,PREPARED 或 CALLABLE。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED。
useGeneratedKeys(仅适用于 insert 和 update)这会令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键(比如:像 MySQL 和 SQL Server 这样的关系型数据库管理系统的自动递增字段),默认值:false。
keyProperty(仅适用于 insert 和 update)指定能够唯一识别对象的属性,MyBatis 会使用 getGeneratedKeys 的返回值或 insert 语句的 selectKey 子元素设置它的值,默认值:未设置(unset)。如果生成列不止一个,可以用逗号分隔多个属性名称。
keyColumn(仅适用于 insert 和 update)设置生成键值在表中的列名,在某些数据库(像 PostgreSQL)中,当主键列不是表中的第一列的时候,是必须设置的。如果生成列不止一个,可以用逗号分隔多个属性名称。
  • 29
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值