四,MyBatis注解

12 篇文章 0 订阅
10 篇文章 0 订阅

1 MyBatis注解引言

MyBatis在设计之初是基于xml配置设计的,xml配置为MyBatis提供了丰富的功能特性,较高的灵活性和可维护性。但尽管如此,xml方式也存在着一些小小的不足:开发效率低。

解决方案:注解开发

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tomwJFEy-1672904202718)(MyBatis day04.assets/image-20210701204624334.png)]

MyBatis3之后提供了另外一种配置方式:注解。

通过注解可以将接口方法和要执行的sql语句定义在一起,提高了开发效率。但需要注意:

  • 注解功能比xml有所不足
  • 注解在开发复杂sql时,编码过于复杂

最佳实践:简单的单表查询SQL用注解,复杂多表关联查询SQL用xml

2 简单操作(CRUD)

public interface UserMapper {
	
	@Insert("insert into t_user values(seq_user.nextval,#{username},#{password})")
	public void insertUser(User u);
	
	@Delete("delete from t_user where user_id = #{id}")
	public void deleteUserById(Integer id);
	@Update("update t_user set user_name = #{username},password=#{password} where user_id = #{userId}")
	public void updateUser(User u);
	
	@Select("select * from t_user where user_id = #{id}")
    //设置实体类型的类对象 等同于标签中resultType属性
	@ResultType(User.class)
	public User selectUserById(Integer id);
	
	@Select("select * from t_user")
	@ResultType(User.class)
	public List<User> selectAllUsers();
}
<!-- 一定要在mybatis.xml中加入-->
<!--指定带有注解的dao接口所在位置,不再需要添加mapper.xml-->
<mappers>
   <mapper class="com.bz.dao.UserDao"></mapper>
</mappers>

总结:

  • 直接在mapper方法上使用 @Insert@Delete@Update@Select 注解,代替xml标签
  • ResultType注解等同于select标签中的resultType属性

3 解决列名和属性名不一致问题

当查询结果和实体属性不一致时,在xml中可以使用 resultMap 标签解决。在注解开发时,应该如何解决?

3.1 复用xml中resultMap标签

可以通过 ResultMap注解复用xml中resultMap标签

  1. 在mapper.xml中定义resultMap标签

    UserMapper.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
    <mapper namespace="com.bz.mapper.UserMapper">
        
        <!-- 定义resultMap标签-->
        <resultMap type="com.bz.entity.User" id="userResultMap1">
            <id column="user_id" property="userId"/>
            <result column="username" property="username"/>
            <result column="password" property="password"/>
        </resultMap>
    
    </mapper>
    
  2. 在mapper查询方法上通过 ResultMap注解 声明使用xml中的resultMap标签

    UserMapper.java

    @Select("select * from t_user")
    //    @ResultType(User.class)
    //ResultType注解替换为ResultMap注解,ResultMap注解等同于xml中resultMap属性
    @ResultMap("userResultMap1")
    public List<User> selectAllUsers();
    
  3. 在mybatis.xml中扫描xml

<mappers>
    <mapper class="com.bz.dao.UserDao"></mapper>
    <mapper resource="UserMapper.xml"></mapper>
</mappers>

3.2 使用Results注解

Results注解等同于xml中的resultMap标签。可以在Mapper.java中使用Results注解代替xml中resultMap标签

UserMapper.java:

	@Select("select * from t_user where user_id = #{id}")
    //设置实体类型的类对象 等同于标签中resultType属性
	//    @ResultType(User.class)
    /**
     <resultMap id="userResultMap1" type="com.bz.entity.User">
        <id column="user_id" property="userId"/>
        <result column="user_name" property="username"/>
        <result column="password" property="password"/>
     </resultMap>
     */
    //Results注解等同于xml中resultMap标签
    @Results(id = "userResultMap2",
        value = {
                @Result(column = "user_id",property = "userId",id=true),
                @Result(column = "user_name",property = "username"),
                @Result(column = "password",property = "password")
        }
    )
    public User selectUserById(Integer id);

注意:

  • ResultMap注解也可以跟Results注解配合使用:ResultMap注解配置成Results注解的id中

  • ResultMap注解Results注解避免同时使用,如果同时使用Results注解将被忽略

4 表连接查询

复习xml中1:N的表连接处理:

  1. create table t_category(
        category_id int primary key ,
        category_name varchar(20) not null unique
    );
    create table t_goods(
        goods_id int primary key ,
        goods_name varchar(20) not null,
        category_id int,
        foreign key (category_id) references t_category(category_id)
    );
    
    insert into t_category
    values (1, '图书');
    insert into t_category
    values (2, '手机');
    insert into t_goods
    values (101, 'Java为什么这么难',1);
    insert into t_goods
    values (102, '活着', 1);
    insert into t_goods
    values (103, 'iphone12',2);
    insert into t_goods
    values (104,'iphone13',2);
    

    连接查询sql

    //根据1查询多的一方
    select c.*,g.*
    from t_category c left join t_goods g
    on c.category_id = g.category_id
    
  2. 实体

    public class Category implements Serializable {
        private Integer categoryId;
        private String categoryName;
    
        private List<Goods> goodsList;
        //无参构造 get/set
    }
    
    public class Goods implements Serializable {
        private Integer goodsId;
        private String goodsName;
        
        //无参构造 get/set
    }
    
  3. 数据转换

    <resultMap type="com.bz.entity.Category" id="categoryResultMap">
    	<id column="category_id" property="categoryId"/>
        <result column="category_name" property="categoryName"/>
         
        <collection property="goodsList" javaType="java.util.List" ofType="com.bz.entity.Goods">
        	<id column="goods_id" property="goodsId"/>
            <result column="goods_name" property="goodsName"/>
        </collection>
        
    </resultMap>
    

注解方式表连接:

  1. 和xml方式下没有区别

  2. 实体

    和xml方式下没有区别

  3. 数据转换

    Results注解在表连接方面没办法替换掉resultMap标签。

    仍然使用resultMap标签,使用ResultMap注解复用resultMap标签。

    <resultMap type="com.bz.entity.Category" id="categoryResultMap">
    	<id column="category_id" property="categoryId"/>
        <result column="category_name" property="categoryName"/>
         
        <collection property="goodsList" javaType="java.util.List" ofType="com.bz.entity.Goods">
        	<id column="goods_id" property="goodsId"/>
            <result column="goods_name" property="goodsName"/>
        </collection>
        
    </resultMap>
    

    接口中:

    @ResultMap("categoryResultMap")
    //进行表连接查询
    @Select("select c.*,g.* from t_category c left join t_goods g on c.category_id = g.category_id")
    public List<Category> selectAllCategory();
    

5 注解中的动态SQL

需求:根据学员姓名、报备老师姓名、口碑奖励查询学员,如果某部分条件没有值,则不再根据该条件查询。

java接口:

 List<RecommendStudent> selectConditionStudents1(@Param("studentName")String studentName,@Param("teacherName")String teacherName,@Param("money")Double money);

mapper.xml:

<resultMap id="recommendStudentResultMap" type="recommendStudent">
    <id column="student_id" property="studentId"/>
    <result column="student_name" property="studentName"/>
    <result column="age" property="age"/>
    <result column="sex" property="sex"/>
    <result column="mobile" property="mobile"/>
    <result column="teacher_name" property="teacherName"/>
    <result column="money" property="money"/>
</resultMap>

<select id="selectConditionStudents1" resultMap="recommendStudentResultMap">
    select * from t_recommend_student
    <where>
        <if test="studentName != null and !studentName.isEmpty()">
            student_name like concat('%',#{studentName},'%')
        </if>
        <if test="teacherName != null and !teacherName.isEmpty()">
            and  teacher_name like concat('%',#{teacherName},'%')
        </if>
        <if test="money != null">
            and money = #{money}
        </if>
    </where>
</select>

5.1 脚本SQL

将mapper.xml中动态sql语句使用

@Select({"<script>",
            "select * from t_recommend_student",
            "<where>",
                " <if test=\"studentName != null and !studentName.isEmpty()\"> ",
                "student_name like concat('%',#{studentName},'%')",
                "</if>",
                "<if test=\"teacherName != null and !teacherName.isEmpty()\">",
                "and  teacher_name like concat('%',#{teacherName},'%')",
                "</if>",
                "<if test=\"money != null\">",
                "and money = #{money}",
                "</if>",
            "</where>",
            "</script>"})
 List<RecommendStudent> selectConditionStudents2(@Param("studentName")String studentName,@Param("teacherName")String teacherName,@Param("money")Double money);

5.2 编程式动态SQL(了解)

5.2.1 编程式动态sql思路

在这里插入图片描述

  • 定义一个类,类中定义一个和mapper方法形参列表相同的方法
  • 方法返回String,在方法中通过if条件判断生成动态的sql语句
  • 在mapper方法上通过 SelectProvider 注解,配置生成sql的方法
  1. 将根据参数生成动态sql的代码抽取成一个方法

    public interface RecommendStudentMapper {
        	
    	
    	@ResultMap("recommendStudentResultMap")
        List<RecommendStudent> selectConditionStudents3(@Param("studentName")String studentName,
                                                        @Param("teacherName")String teacherName,
                                                        @Param("money")Double money);
    	
    	//RecommendStudentMapperSqlProvider做成接口内部类,方便使用
    	 public static class RecommendStudentMapperSqlProvider{
    
            public String selectConditionStudents3(@Param("studentName")String studentName,
                                                   @Param("teacherName")String teacherName,
                                                   @Param("money")Double money){
                String sql = "select * from t_recommend_student";
                boolean checkUsername = studentName != null && !studentName.isEmpty();
                boolean checkTeacherName = teacherName != null && !teacherName.isEmpty();
                boolean checkMoney = money != null;
                if(checkUsername || checkTeacherName || checkMoney){
                    sql += " where ";
    
                    if (checkUsername) {
                        sql += "student_name like concat('%',#{studentName},'%')";
                    }
    
                    if(checkTeacherName){
                        if(checkUsername){
                            sql += " and ";
                        }
                        sql += "teacher_name like concat('%',#{teacherName},'%')";
                    }
    
                    if(checkMoney){
                        if(checkUsername || checkTeacherName){
                            sql += " and ";
                        }
                        sql += "money = #{money}";
                    }
                }
                return sql;
            } 
    
        }
    }
    
  2. 在接口方法上调用生成动态sql的方法

    public interface RecommendStudentMapper {
        	
    	@ResultMap("recommendStudentResultMap")
        /* 
        	type:生成动态sql方法所在类的类对象
        	method:生成动态sql方法的名
        */
    	@SelectProvider(type = RecommendStudentMapperSqlProvider.class,method = "selectConditionStudents3")
        @ResultMap("recommendStudentResultMap")
        List<RecommendStudent> selectConditionStudents3(@Param("studentName")String studentName,
                                                        @Param("teacherName")String teacherName,
                                                        @Param("money")Double money);
    	
    	...
    }
    
5.2.2 更多的动态SQL注解

SelectProvider注解专为查询方法配置生成sql语句的方法。如果是增、删、改方法,则使用 @InsertProvider@DeleteProvider@UpdateProvider注解。

@DeleteProvider(type=生成动态sql方法所在类.class,method="生成sql方法名")

@InsertProvider(type=生成动态sql方法所在类.class,method="生成sql方法名")

@UpdateProvider(type=生成动态sql方法所在类.class,method="生成sql方法名")

@SelectProvider(type=生成动态sql方法所在类.class,method="生成sql方法名")

四个注解除了标注的方法类型不同,在使用中并没有别的差异!!!

5.2.3 List参数的特殊要求

如果mapper方法形参列表只有一个List参数,生成动态SQL语句的方法形参列表要做特殊处理!!!

  • 如果List形参未使用注解,则动态SQL方法的List形参前要添加 @Param("list")

在这里插入图片描述

  • 如果List形参使用了注解,则动态SQL方法的List形参前要添加 @Param("相同的注解名")

在这里插入图片描述

5.2.4 SQL类简化动态SQL

SQL类:简化注解动态SQL的生成。

public String selectConditionStudents4(@Param("studentName")String studentName,
                                               @Param("teacherName")String teacherName,
                                               @Param("money")Double money){
    SQL sql = new SQL();//生成动态SQL的工具
    sql.SELECT("*")
        .FROM("t_recommend_student");
    if(studentName != null && !studentName.isEmpty()){
        sql.WHERE("student_name like concat('%',#{studentName},'%')");
    }
    if (teacherName != null && !teacherName.isEmpty()) {
        sql.WHERE("teacher_name like concat('%',#{teacherName},'%')");
    }
    if (money != null) {
        sql.WHERE("money = #{money}");
    }

    return sql.toString();
}

6 其它注解

6.1 缓存相关注解

@CacheNamespace//类似于mapper.xml的cache标签
public interface UserMapper {
}

@CacheNamespaceRef(name = "另外一个Mapper的namespace")
public interface UserMapper {
}

6.2 Options注解

封装了insert、delete、update、select标签中一些属性,通过Options注解可以设置这些属性值。

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
SpringBoot整合Mybatis注解是指在SpringBoot框架中使用Mybatis注解来进行数据库操作的一种方式。通过引入相应的依赖,配置文件和注解,可以方便地实现数据的增删改查操作。 在整合Mybatis注解时,首先需要在pom.xml文件中引入相关的依赖,包括mybatis-spring-boot-starter和mysql-connector-java。这些依赖会提供Mybatis和数据库连接的功能。 接下来,需要配置Mybatis的相关信息,例如数据库连接信息和Mapper接口的扫描路径。这些配置信息通常可以在application.properties或application.yml文件中进行配置。 在实体层(Entities)、dao层(Data Access Objects)、service层和controller层可以使用Mybatis注解来进行数据库操作。例如,在dao层的Mapper接口中使用@Insert、@Update、@Delete和@Select等注解来定义相应的SQL语句。 最后,整个工程的结构可以根据实际需求进行组织,一般包括实体层、dao层、service层和controller层。 通过以上步骤,就可以实现SpringBoot和Mybatis注解整合,实现对数据库的操作。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [SpringBoot整合Mybatis注解详细版](https://blog.csdn.net/weixin_42841433/article/details/102310489)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

斑马有点困

原创不易,多谢打赏

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值