Mybatis注解用法

2024-09-08 01:18
文章标签 用法 注解 mybatis

本文主要是介绍Mybatis注解用法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

  • MyBatis(八) mybatis注解
    • 一、mybatis简单注解
      • 1、@Select、@Results、@Result
      • 2、@Delete、@Param、@ResultMap
      • 3、@Insert、@SelectKey
      • 4、@Delete、@Param
      • 5、@Update
    • 二、动态SQL
      • 1、简单处理,直接使用``脚本
      • 2、使用Provider注解标识
        • 2.1、创建Provider类
        • 2.2、注解使用Provider类
    • 三、注解使用多表关联查询
      • 1、使用子查询方式
        • 1.1、多对一或者一对一中的一端写法 @One
        • 1.2、一对多或者多对多中的多端写法 @Many
      • 2、N+1问题
      • 3、最佳实践-注解与xml结合使用
        • 3.1、xml文件配置resultMap,这样方便多个接口调用
        • 3.2、配置映射
        • 3.3、注解代码
          • 3.3.1、简单的注解代码
          • 3.3.2、复杂的代码可以结合使用Provider
    • 四、Mybatis全部注解列表

MyBatis(八) mybatis注解

一、mybatis简单注解

 
  • @Insert : 插入sql , 和xml insert sql语法完全一样@Select : 查询sql, 和xml select sql语法完全一样
  • @Update : 更新sql, 和xml update sql语法完全一样
  • @Delete : 删除sql, 和xml delete sql语法完全一样
  • @Param : 入参
  • @Results : 设置结果集合@Result : 结果
  • @ResultMap : 引用结果集合
  • @SelectKey : 获取最新插入id

less

具体使用:

1、@Select、@Results、@Result

 
  • /**
  • * 查询所有
  • * @return Employee泛型集合
  • */
  • @Select("select * from t_emp")
  • @Results(id = "empMap",value = {
  • @Result(column = "emp_id",property = "empId",id = true),
  • @Result(column = "emp_name",property = "empName"),
  • @Result(column = "emp_tel",property = "empTel"),
  • @Result(column = "emp_education",property = "empEducation"),
  • @Result(column = "emp_birthday",property = "empBirthday"),
  • @Result(column = "fk_dept_id",property = "dept"
  • ,one = @One(select = "com.yingside.dao.DeptMapper.getById",
  • fetchType = FetchType.LAZY))
  • })
  • List<Employee> getAll();

java

2、@Delete、@Param、@ResultMap

 
  • /**
  • * 根据id查询员工
  • * @param empId 员工主键id
  • * @return 员工对象
  • */
  • @Select("select * from t_emp where emp_id=#{empId}")
  • @ResultMap(value="empMap")
  • Employee getById(@Param("empId") Integer empId);

java

3、@Insert、@SelectKey

 
  • /**
  • * 插入新员工信息,并将最新id放入到员工对象在
  • * @param record 新员工对象
  • * @return 插入成功 1 失败 0
  • */
  • @Insert("insert into t_emp (emp_id, emp_name, emp_tel, " +
  • " emp_education, emp_birthday, fk_dept_id" +
  • " )" +
  • " values (#{empId}, #{empName}, #{empTel}, " +
  • " #{empEducation}, #{empBirthday}, #{fkDeptId}" +
  • " )")
  • @SelectKey(before = false,keyColumn = "emp_id",keyProperty = "empId",
  • statement = "select last_insert_id()",resultType = Integer.class)
  • int insert(Employee record);

java

4、@Delete、@Param

 
  • /**
  • * 根据员工id删除员工
  • * @param empId 员工主键id
  • * @return 删除成功 1 失败 0
  • */
  • @Delete("delete from t_emp where emp_id=#{empId}")
  • int deleteByPrimaryKey(@Param("empId") Integer empId);

java

5、@Update

 
  • /**
  • * 更新员工信息
  • * @param record 员工对象
  • * @return 更新成功 1 失败 0
  • */
  • @Update("update t_emp" +
  • " set emp_name = #{empName,jdbcType=VARCHAR}," +
  • " emp_tel = #{empTel,jdbcType=VARCHAR}," +
  • " emp_education = #{empEducation,jdbcType=VARCHAR}," +
  • " emp_birthday = #{empBirthday,jdbcType=DATE}," +
  • " fk_dept_id = #{fkDeptId,jdbcType=INTEGER}" +
  • " where emp_id = #{empId,jdbcType=INTEGER}")
  • int update(Employee record);

java

当然最后别忘记了,写完这些之后,在核心配置文件中要把映射文件给加上,之前使用的时候,找寻的是resouce xml的资源路径,现在由于使用了注解,就只有接口文件了,所有配置相应的要做一个简单的修改

 
  • <mappers>
  • <mapper class="com.yingside.dao.EmployeeMapper" />
  • </mappers>

二、动态SQL

1、简单处理,直接使用<script>脚本

 
  • /**
  • * script实现动态sql更新员工信息
  • * @param record 员工对象
  • * @return 更新成功 1 失败 0
  • */
  • @Update("<script>" +
  • "update t_emp" +
  • " <set >" +
  • " <if test=\"empName != null\" >" +
  • " emp_name = #{empName,jdbcType=VARCHAR},\n" +
  • " </if>" +
  • " <if test=\"empTel != null\" >" +
  • " emp_tel = #{empTel,jdbcType=VARCHAR}," +
  • " </if>" +
  • " <if test=\"empEducation != null\" >" +
  • " emp_education = #{empEducation,jdbcType=VARCHAR}," +
  • " </if>" +
  • " <if test=\"empBirthday != null\" >" +
  • " emp_birthday = #{empBirthday,jdbcType=DATE}," +
  • " </if>" +
  • " <if test=\"fkDeptId != null\" >" +
  • " fk_dept_id = #{fkDeptId,jdbcType=INTEGER}," +
  • " </if>" +
  • " </set>" +
  • " where emp_id = #{empId,jdbcType=INTEGER}" +
  • "</script>")
  • int updateByPrimaryKeySelective(Employee record);

java

2、使用Provider注解标识

增删改查,每一个都有一个对应的Provider注解标识

 
  • @Insert :@InsertProvider
  • @Select :@SelectProvider
  • @Update :@UpdateProvider
  • @Delete :@DeleteProvider

java

使用:

2.1、创建Provider类

 
  • public class EmployeeProvider {
  • public String updateSQL(Employee emp) {
  • return new SQL() {
  • {
  • UPDATE("t_emp");
  • if (emp.getEmpName() != null) {
  • SET("emp_name = #{empName}");
  • }
  • if (emp.getEmpTel() != null) {
  • SET("emp_tel = #{empTel}");
  • }
  • if (emp.getEmpEducation() != null) {
  • SET("emp_education = #{empEducation}");
  • }
  • if (emp.getEmpBirthday() != null) {
  • SET("emp_birthday = #{empBirthday}");
  • }
  • if (emp.getFkDeptId() != null) {
  • SET("fk_dept_id = #{fkDeptId}");
  • }
  • WHERE("emp_id = #{empId}");
  • }
  • }.toString();
  • }
  • }

java

这里使用的Provider的一些关键字

掌握最重要的一点,Provider其实就是要返回一个SQL字符串 只不过用了一些关键字做格式化而已,其实不使用也可以 完全可以使用String字符串拼接SQL语句,当然复杂的语句还是建议使用StringBuilder或者StringBuffer拼接

2.2、注解使用Provider类

 
  • @UpdateProvider(type = EmployeeProvider.class, method = "updateSQL")
int updateBySelectiveProvider(Employee record);

三、注解使用多表关联查询

1、使用子查询方式

1.1、多对一或者一对一中的一端写法 @One

这种查询方式和之前在xml中介绍的第二种方式一样,相当于就是一个子查询先查询员工,再根据员工查询出来的部门外键查询部门信息,最后再把查询出来的信息放入到Employee对象中的Dept属性中

EmployeeMapper.java 接口:

 
  • /**
  • * 查询所有
  • * @return Employee泛型集合
  • */
  • @Select("select * from t_emp")
  • @Results(id = "empMap",value = {
  • @Result(column = "emp_id",property = "empId",id = true),
  • @Result(column = "emp_name",property = "empName"),
  • @Result(column = "emp_tel",property = "empTel"),
  • @Result(column = "emp_education",property = "empEducation"),
  • @Result(column = "emp_birthday",property = "empBirthday"),
  • @Result(column = "fk_dept_id",property = "dept"
  • ,one = @One(select = "com.yingside.dao.DeptMapper.getById",
  • fetchType = FetchType.LAZY))
  • })
  • List<Employee> getAll();

java

DeptMapper.java 接口:

 
  • public interface DeptMapper {
  • @Results(id="deptMap",value = {
  • @Result(column = "dept_id",property = "deptId",id = true),
  • @Result(column = "dept_name",property = "deptName"),
  • @Result(column = "dept_info",property = "deptInfo"),
  • @Result(column = "dept_createDate",property = "deptCreatedate")
  • })
  • @Select("select * from t_dept where dept_id=#{deptId}")
  • Dept getById(@Param("deptId") Integer deptId);
  • }

java

1.2、一对多或者多对多中的多端写法 @Many

通过子查询,先查询部门信息再通过部门主键,在员工外键表中查询和部门相关联的员工信息

DeptMapper.java 接口:

 
  • public interface DeptMapper {
  • @Results(id="deptMap",value = {
  • @Result(column = "dept_id",property = "deptId",id = true),
  • @Result(column = "dept_name",property = "deptName"),
  • @Result(column = "dept_info",property = "deptInfo"),
  • @Result(column = "dept_createDate",property = "deptCreatedate"),
  • @Result(column = "dept_id",property = "employeeList"
  • ,many = @Many(select = "com.yingside.dao.EmployeeMapper.getEmpsByDeptId",
  • fetchType = FetchType.LAZY))
  • })
  • @Select("select * from t_dept where dept_id=#{deptId}")
  • Dept getById(@Param("deptId") Integer deptId);
  • }

java

EmployeeMapper.java 接口:

 
  • public interface EmployeeMapper {
  • //......其他代码省略
  • /**
  • * 根据部门id查询部门下所有员工
  • * @param fkDeptId 部门id
  • * @return 员工的泛型集合
  • */
  • @Select("select * from t_emp where fk_dept_id=#{fkDeptId}")
  • //@ResultMap("empMap")
  • List<Employee> getEmpsByDeptId(@Param("fkDeptId") int fkDeptId);
  • }

java

2、N+1问题

注意:像上面这种通过子查询的方式实现关联查询,最好就只是查询一个方向就行了,意思是,要么通过员工查询部门,要么就通过部门查询员工。不要两个都写。上面的例子只是简单说明一端多端的写法。如果两个都写的话,就会引起循环引用的问题,查员工的时候发现要子查询部门,查了部门发现又要查员工......就会报出下面的错误:

 
  • java.lang.StackOverflowError

所以,最佳实践:尽量不要出现这种情况的互相引用。这种子查询的方式,建议是在必须使用懒加载的情况下使用。如果一般情况的多表查询,还是使用表的级联分页查询,inner,left,right join等

3、最佳实践-注解与xml结合使用

3.1、xml文件配置resultMap,这样方便多个接口调用

3.2、配置映射

3.3、注解代码

3.3.1、简单的注解代码

 
  • /**
  • * 通过级联查询查询员工信息
  • * @return 员工的泛型集合
  • */
  • @Select("select * from t_emp join t_dept on t_emp.fk_dept_id = t_dept.dept_id")
  • @ResultMap("com.yingside.mapper.EmployeeMapper.employeeMap")
  • List<Employee> getAllJoin();

java

注意这里@ResultMap的值是xml文件的地址

3.3.2、复杂的代码可以结合使用Provider

EmployeeProvider.java

 
  • package com.yingside.provider;
  • import com.yingside.po.Employee;
  • import org.apache.ibatis.jdbc.SQL;
  • import java.util.Map;
  • public class EmployeeProvider {
  • //......其他代码省略
  • public String selectListProvider(Map<String,Object> map){
  • return new SQL(){
  • {
  • SELECT(" t_emp.emp_id," +
  • " t_emp.emp_name," +
  • " t_emp.emp_tel," +
  • " t_emp.emp_education," +
  • " t_emp.emp_birthday," +
  • " t_dept.dept_id," +
  • " t_dept.dept_name," +
  • " t_dept.dept_info," +
  • " t_dept.dept_createDate");
  • FROM("t_emp");
  • LEFT_OUTER_JOIN("t_dept on t_emp.fk_dept_id = t_dept.dept_id");
  • if (map.get("empName") != null){
  • AND().WHERE("t_emp.emp_name like concat('%',#{empName},'%')");
  • }
  • if (map.get("empTel") != null){
  • AND().WHERE("t_emp.emp_tel like concat('%',#{empTel},'%')");
  • }
  • if (map.get("deptId") != null){
  • AND().WHERE("t_dept.dept_id=#{deptId}");
  • }
  • }}.toString();
  • }
  • }

java

EmployeeDao.java

 
  • /**
  • * 通过级联查询动态sql Provider查询员工新
  • * @param map 键值对的参数
  • * @return 员工的泛型集合
  • */
  • @SelectProvider(type = EmployeeProvider.class, method = "selectListProvider")
  • @ResultMap("com.yingside.mapper.EmployeeMapper.employeeMap")
  • List<Employee> getAllJoinProvider(Map<String,Object> map);

java

测试

 
  • @Test
  • public void testGetAllJoinProvider(){
  • EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
  • Map<String,Object> map = new HashMap<>();
  • map.put("empName","公");
  • map.put("deptId",1);
  • List<Employee> all = mapper.getAllJoinProvider(map);
  • log.info(all);
  • sqlSession.commit();
  • }

java

四、Mybatis全部注解列表

注解目标相对应的 XML描述
@CacheNamespace<cache>为给定的命名空间 (比如类) 配置缓存。 属性:implemetation,eviction, flushInterval,size 和 readWrite。
@CacheNamespaceRef<cacheRef>参照另外一个命名空间的缓存来使用。 属性:value,应该是一个名空间的字 符串值(也就是类的完全限定名) 。
@ConstructorArgs方法<constructor>收集一组结果传递给一个劫夺对象的 构造方法。属性:value,是形式参数 的数组。
@Arg方法<arg>``<idArg>单 独 的 构 造 方 法 参 数 , 是 ConstructorArgs 集合的一部分。属性: id,column,javaType,typeHandler。 id 属性是布尔值, 来标识用于比较的属 性,和XML 元素相似。
@TypeDiscriminator方法<discriminator>一组实例值被用来决定结果映射的表 现。 属性: column, javaType, jdbcType, typeHandler,cases。cases 属性就是实 例的数组。
@Case方法<case>单独实例的值和它对应的映射。属性: value,type,results。Results 属性是结 果数组,因此这个注解和实际的 ResultMap 很相似,由下面的 Results 注解指定。
@Results方法<resultMap>结果映射的列表, 包含了一个特别结果 列如何被映射到属性或字段的详情。 属 性:value, id。value 属性是 Result 注解的数组。 The id attribute is the name of the result mapping.
@Result方法<result>``<id>在列和属性或字段之间的单独结果映 射。属 性:id,column, property, javaType ,jdbcType ,type Handler, one,many。id 属性是一个布尔值,表 示了应该被用于比较(和在 XML 映射 中的相似)的属性。one 属性是单 独 的 联 系, 和 <association> 相 似 , 而 many 属 性 是 对 集 合 而 言 的 , 和 <collection>相似。 它们这样命名是为了 避免名称冲突。
@One方法<association>复杂类型的单独属性值映射。属性: select,已映射语句(也就是映射器方 法)的完全限定名,它可以加载合适类 型的实例。注意:联合映射在注解 API 中是不支持的。这是因为 Java 注解的 限制,不允许循环引用。 fetchType, which supersedes the global configuration parameterlazyLoadingEnabled for this mapping.
@Many方法<collection>A mapping to a collection property of a complex type. Attributes: select, which is the fully qualified name of a mapped statement (i.e. mapper method) that can load a collection of instances of the appropriate types,fetchType, which supersedes the global configuration parameterlazyLoadingEnabled for this mapping. NOTE You will notice that join mapping is not supported via the Annotations API. This is due to the limitation in Java Annotations that does not allow for circular references.
@MapKey方法 复 杂 类 型 的 集合 属 性 映射 。 属 性 : select,是映射语句(也就是映射器方 法)的完全限定名,它可以加载合适类 型的一组实例。注意:联合映射在 Java 注解中是不支持的。这是因为 Java 注 解的限制,不允许循环引用。
@Options方法映射语句的属性这个注解提供访问交换和配置选项的 宽广范围, 它们通常在映射语句上作为 属性出现。 而不是将每条语句注解变复 杂,Options 注解提供连贯清晰的方式 来访问它们。属性:useCache=true , flushCache=FlushCachePolicy.DEFAULT , resultSetType=FORWARD_ONLY , statementType=PREPARED , fetchSize=-1 , , timeout=-1 useGeneratedKeys=false , keyProperty=”id” , keyColumn=”” , resultSets=””。 理解 Java 注解是很 重要的,因为没有办法来指定“null” 作为值。因此,一旦你使用了 Options 注解,语句就受所有默认值的支配。要 注意什么样的默认值来避免不期望的 行为。 @Insert``@Update``@Delete``@Select方法<insert>``<update>``<delete>``<select>这些注解中的每一个代表了执行的真 实 SQL。 它们每一个都使用字符串数组 (或单独的字符串)。如果传递的是字 符串数组, 它们由每个分隔它们的单独 空间串联起来。这就当用 Java 代码构 建 SQL 时避免了“丢失空间”的问题。 然而,如果你喜欢,也欢迎你串联单独 的字符串。属性:value,这是字符串 数组用来组成单独的 SQL 语句。 @InsertProvider``@UpdateProvider``@DeleteProvider``@SelectProvider 方法<insert>``<update>``<delete>``<select>这些可选的 SQL 注解允许你指定一个 类名和一个方法在执行时来返回运行 允许创建动态 的 SQL。 基于执行的映射语句, MyBatis 会实例化这个类,然后执行由 provider 指定的方法. 该方法可以有选择地接受参数对象.(In MyBatis 3.4 or later, it’s allow multiple parameters) 属性: type,method。type 属性是类。method 属性是方法名。 注意: 这节之后是对 类的 讨论,它可以帮助你以干净,容于阅读 的方式来构建动态 SQL。
@ParamParameter 如果你的映射器的方法需要多个参数, 这个注解可以被应用于映射器的方法 参数来给每个参数一个名字。否则,多 参数将会以它们的顺序位置来被命名 (不包括任何 RowBounds 参数) 比如。 #{param1} , #{param2} 等 , 这 是 默 认 的 。 使 用 @Param(“person”),参数应该被命名为 #{person}。
@SelectKey方法<selectKey>This annotation duplicates the functionality for methods annotated with @Insert, @InsertProvider, @Update or@UpdateProvider. It is ignored for other methods. If you specify a@SelectKey annotation, then MyBatis will ignore any generated key properties set via the @Options annotation, or configuration properties. Attributes: statement an array of strings which is the SQL statement to execute, keyProperty which is the property of the parameter object that will be updated with the new value, before which must be either true orfalse to denote if the SQL statement should be executed before or after the insert, resultType which is the Java type of the keyProperty, andstatementType=PREPARED.
@ResultMap方法 This annotation is used to provide the id of a <resultMap> element in an XML mapper to a @Select or @SelectProvider annotation. This allows annotated selects to reuse resultmaps that are defined in XML. This annotation will override any @Results or @ConstructorArgs annotation if both are specified on an annotated select.
@ResultType方法 This annotation is used when using a result handler. In that case, the return type is void so MyBatis must have a way to determine the type of object to construct for each row. If there is an XML result map, use the @ResultMap annotation. If the result type is specified in XML on the<select> element, then no other annotation is necessary. In other cases, use this annotation. For example, if a @Select annotated method will use a result handler, the return type must be void and this annotation (or @ResultMap) is required. This annotation is ignored unless the method return type is void.
@Flush方法 If this annotation is used, it can be called theSqlSession#flushStatements() via method defined at a Mapper interface.(MyBatis 3.3 or above)

本文链接:http://www.yanhongzhi.com/post/mybatis-annotation.html

这篇关于Mybatis注解用法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1146698

相关文章

JavaScript中的reduce方法执行过程、使用场景及进阶用法

《JavaScript中的reduce方法执行过程、使用场景及进阶用法》:本文主要介绍JavaScript中的reduce方法执行过程、使用场景及进阶用法的相关资料,reduce是JavaScri... 目录1. 什么是reduce2. reduce语法2.1 语法2.2 参数说明3. reduce执行过程

mybatis和mybatis-plus设置值为null不起作用问题及解决

《mybatis和mybatis-plus设置值为null不起作用问题及解决》Mybatis-Plus的FieldStrategy主要用于控制新增、更新和查询时对空值的处理策略,通过配置不同的策略类型... 目录MyBATis-plusFieldStrategy作用FieldStrategy类型每种策略的作

在 Spring Boot 中使用 @Autowired和 @Bean注解的示例详解

《在SpringBoot中使用@Autowired和@Bean注解的示例详解》本文通过一个示例演示了如何在SpringBoot中使用@Autowired和@Bean注解进行依赖注入和Bean... 目录在 Spring Boot 中使用 @Autowired 和 @Bean 注解示例背景1. 定义 Stud

Python itertools中accumulate函数用法及使用运用详细讲解

《Pythonitertools中accumulate函数用法及使用运用详细讲解》:本文主要介绍Python的itertools库中的accumulate函数,该函数可以计算累积和或通过指定函数... 目录1.1前言:1.2定义:1.3衍生用法:1.3Leetcode的实际运用:总结 1.1前言:本文将详

SpringBoot+MyBatis-Flex配置ProxySQL的实现步骤

《SpringBoot+MyBatis-Flex配置ProxySQL的实现步骤》本文主要介绍了SpringBoot+MyBatis-Flex配置ProxySQL的实现步骤,文中通过示例代码介绍的非常详... 目录 目标 步骤 1:确保 ProxySQL 和 mysql 主从同步已正确配置ProxySQL 的

MyBatis-Flex BaseMapper的接口基本用法小结

《MyBatis-FlexBaseMapper的接口基本用法小结》本文主要介绍了MyBatis-FlexBaseMapper的接口基本用法小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具... 目录MyBATis-Flex简单介绍特性基础方法INSERT① insert② insertSelec

Spring排序机制之接口与注解的使用方法

《Spring排序机制之接口与注解的使用方法》本文介绍了Spring中多种排序机制,包括Ordered接口、PriorityOrdered接口、@Order注解和@Priority注解,提供了详细示例... 目录一、Spring 排序的需求场景二、Spring 中的排序机制1、Ordered 接口2、Pri

Idea实现接口的方法上无法添加@Override注解的解决方案

《Idea实现接口的方法上无法添加@Override注解的解决方案》文章介绍了在IDEA中实现接口方法时无法添加@Override注解的问题及其解决方法,主要步骤包括更改项目结构中的Languagel... 目录Idea实现接China编程口的方法上无法添加@javascriptOverride注解错误原因解决方

Java中基于注解的代码生成工具MapStruct映射使用详解

《Java中基于注解的代码生成工具MapStruct映射使用详解》MapStruct作为一个基于注解的代码生成工具,为我们提供了一种更加优雅、高效的解决方案,本文主要为大家介绍了它的具体使用,感兴趣... 目录介绍优缺点优点缺点核心注解及详细使用语法说明@Mapper@Mapping@Mappings@Co

深入解析Spring TransactionTemplate 高级用法(示例代码)

《深入解析SpringTransactionTemplate高级用法(示例代码)》TransactionTemplate是Spring框架中一个强大的工具,它允许开发者以编程方式控制事务,通过... 目录1. TransactionTemplate 的核心概念2. 核心接口和类3. TransactionT