MyBatis框架核心之注解使用resultMap及多表查询

前几天还觉得注解麻烦,突然恍然大悟,觉得注解相较于传统的mapper.xml+接口,xml使用接口映射相对较麻烦,所以我们可以使用注解来简化开发。
本文简单介绍一下@Results、@Result、@One和@Many的用法,该注解主要是代替resultMap标签和其子标签,还有一些通过注解crud的用法 学艺不精 还望多多指教

一、resultMap简介

MyBatis是基于“数据库结构不可控”的思想建立的,结果集映射就是MyBatis为我们提供这种理想与现实间转换的手段了,而resultMap就是结果集映射的配置标签了。有没有想到Resultset?哈哈有了mybatis就再也不用手写那些重复的步骤了,Mybatis是什么就不在这里介绍了

1.resultMap简介

在深入ResultMap标签前,我们需要了解从SQL查询结果集到JavaBean或POJO实体的过程。

  1. 通过JDBC查询得到ResultSet对象

  2. 遍历ResultSet对象并将每行数据暂存到HashMap实例中,以结果集的字段名或字段别名为键,以字段值为值

  3. 根据ResultMap标签的type属性通过反射实例化领域模型

  4. 根据ResultMap标签的type属性和id、result等标签信息将HashMap中的键值对,填充到领域模型实例中并返回

2.使用场景

   在项目的实际开发中,有可能会遇到这样两种情况。
  1. 属性名和字段名不一致的情况,一种解决方法是使用别名,例如pwd as password,另一种就是使用结果集映射

  2. 多表查询的返回值中可能需要其他对象,或者数组(一对一和一对多)

二.resultMap对应的注解和用法

首先创建一个表
实体字段

实体字段 表的列名
sid stuid
sname stuname
gid gid
grade grade

1.@Results注解

代替的是标签resultMap

该注解中可以使用单个@Result注解,也可以使用@Result集合

@Results({@Result(),@Result()})或@Results(@Result())

注意:使用注解是若报出org.apache.ibatis.binding.BindingException:Invalid bound statement (not found):接口全类名.方法名

可能是使用@Results注解时忘记使用@Select注解

@Results({@Result(column="stuid",property="sid"),@Result(column="stuname",property="sname")})

@Select("select * from student where gid=#{0}")

public List<Student> queryStudentByGid();

2.@Result注解

代替了 id标签和result标签

@Result 中 属性介绍:

column 数据库的列名

Property需要装配的属性名

one 需要使用的@One注解(@Result(one=@One)()))

many 需要使用的@Many注解(@Result(many=@many)()))

前两种肯定不陌生了,主要介绍one和many的用法。

@One注解(一对一)

代替了assocation标签,是多表查询的关键,在注解中用来指定子查询返回单一对象。

@One注解属性介绍:

select 指定用来多表查询的sqlmapper

fetchType会覆盖全局的配置参数lazyLoadingEnabled

所谓lazyLoadingEnabled就是懒加载,也称为延迟加载,只有在你需要的时候才查询表单

使用格式:

@Result(column=" “,property=”",one=@One(select=""))

例如:在获取某个学生的信息的同时又想获取所属班级的所有信息

学生实体中的字段

public class Student {

     private Integer sid;//学生id

     private String sname; //学生姓名

     private Integer gid; //班级id

     private Grade grade; //所属班级的所有信息

}

班级实体的字段

import java.util.List;
public class Grade {

    private Integer id;//班级id

    private String gname;//班级名称

       public Grade() {

       super();

       // TODO Auto-generated constructor stub

    }
}

在Student的字段中,Grade班级实体,需要查询班级表才能获取,学生表中没有该列(所以需要使用多表查询中,一对一关系,的 @Result中的one属性 和@One注解)

@Results({

@Result(column="stuid",property="sid"),

@Result(column="stuname",property="sname"),

@Result(column="gid",property="grade",one=@One(select="cn.et.fuqiang.resultMap.annotation.GradeAnnotationInterface.gradeInStudent"))})

   @Select("select * from student")

   public List<Student> queryAllStudent();

解析:

因为表中的字段与实体中的不同,所以使用了这两个注解,将表的列与实体的属

@Result(column=“stuid”,property=“sid”),

@Result(column=“stuname”,property=“sname”),

因为实体中还有一个班级实体属性,但表中没有该字段,所以就要用多表查询

@Result(column=“gid”,property=“grade”,one=@One(select=“cn.et.fuqiang.resultMap.annotation.GradeAnnotationInterface.gradeInStudent”))

(这里的property是实体中的字段,而column=gid就相当于关联的条件了

而select就是该关联条件对应的查询方法)

在namespace="cn.et.fuqiang.resultMap.annotation.GradeAnnotationInterface下的方法

@Results(@Result(property="id",column="gid"))

@Select("select * from grade where gid=#{0}")

public Grade gradeInStudent();

@Many注解(多对一)

       代替了Collection标签,是是多表查询的关键,在注解中用来指定子查询返回对象集合。

注意:聚集元素用来处理“一对多”的关系。需要指定映射的Java实体类的属性,属性的javaType(一般为ArrayList)但是注解中可以不定义;

使用格式:

@Result(property="",column="",many=@Many(select=""))

代码和如上类似,可以通过班级和学生的关系来实现。

3.增删改查

比较常用也好理解 上代码直接

     @Insert({" insert into category_ ( name ) values (#{name}) "})
    int add(Category var1);

    @Delete({" delete from category_ where id= #{id} "})
    void delete(int var1);

    @Select({"select * from category_ where id= #{id} "})
    Category get(int var1);

    @Update({"update category_ set name=#{name} where id=#{id} "})
    int update(Category var1);
    @Select("select count(*) from category_")
    public int count();
public class TestMybatis {
   
    public static void main(String[] args) throws IOException {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession session = sqlSessionFactory.openSession();
        CategoryMapper mapper = session.getMapper(CategoryMapper.class);
  
//        add(mapper);
//        delete(mapper);
//        get(mapper);
//        update(mapper);
        listAll(mapper);
              
        session.commit();
        session.close();
   
    }
  
    private static void update(CategoryMapper mapper) {
        Category c= mapper.get(8);
        c.setName("修改了的Category名稱");
        mapper.update(c);
        listAll(mapper);
    }
  
    private static void get(CategoryMapper mapper) {
        Category c= mapper.get(8);
        System.out.println(c.getName());
    }
  
    private static void delete(CategoryMapper mapper) {
        mapper.delete(2);
        listAll(mapper);
    }
  
    private static void add(CategoryMapper mapper) {
        Category c = new Category();
        c.setName("新增加的Category");
        mapper.add(c);
        listAll(mapper);
    }
   
    private static void listAll(CategoryMapper mapper) {
        List<Category> cs = mapper.list();
        for (Category c : cs) {
            System.out.println(c.getName());
        }
    }
}

和xml映射方法不同的只不过是将sql语句写到上面去了

发布了20 篇原创文章 · 获赞 0 · 访问量 286

猜你喜欢

转载自blog.csdn.net/Vince_Wang1/article/details/104067485