Mybatis高级阶段

Mybatis基于注解开发

这几年来注解开发越来越流行,Mybatis也可以使用注解开发方式,这样我们就可以减少编写Mapper映射文件了

注解 说明
@Insert 实现新增
@Update 实现更新
@Delete 实现删除
@Select 实现查询
@Result 实现结果集封装
@Results 可以与@Result 一起使用,封装多个结果集
@One 实现一对一结果集封装
@Many 实现一对多结果集封装
    @Select("select * from student")
    public List<Student> findAll();

    @Insert("insert into student values (#{sid}, #{sname}, #{age}, #{birthday})")
    @Options(useGeneratedKeys = true, keyColumn = "sid", keyProperty = "sid") //此操作只限于新增操作后放回主键值
    int addStu(Student student);

    @Update("update student set sname = #{sname}, age = #{age}, birthday = #{birthday} where sid = #{sid}")
    int updateStu(Student student);
    
    @Delete("delete from student where sid = #{id}")
    int deleteStu(Integer id);

注意:修改MyBatis的核心配置文件,我们使用了注解替代的映射文件,所以我们只需要加载使用了注解的Mapper接口即可

<mappers>
    <!--扫描使用注解的类-->
    <mapper class="com.itheima.mapper.UserMapper"></mapper>
</mappers>

或者指定扫描包含映射关系的接口所在的包也可以

<mappers>
    <!--扫描使用注解的类所在的包-->
    <package name="com.itheima.mapper"></package>
</mappers>

Mybatis基于注解实现多表操作

实现复杂关系映射之前我们可以在映射文件中通过配置<resultMap>,<result>,<association>,<collection>组合来实现,使用注解开发后,我们可以使用@Results注解,@Result注解,@One注解,@Many注解组合完成复杂关系的配置


测试数据来源于Mybatis进阶阶段

一对一操作

//PersonMapper接口
public interface PersonMapper {
    //根据id查询
    @Select("SELECT * FROM person WHERE id=#{id}")
    public abstract Person selectById(Integer id);
}
//CardMapper接口
public interface CardMapper {
    //查询全部
    @Select("SELECT * FROM card")
    @Results({
            @Result(column = "id",property = "id"),
            @Result(column = "number",property = "number"),
            @Result(
                    property = "p",             // 被包含对象的变量名
                    javaType = Person.class,    // 被包含对象的实际数据类型
                    column = "pid",             // 根据查询出的card表中的pid字段来查询person表
                    /*
                        one、@One 一对一固定写法
                        select属性:指定调用哪个接口中的哪个方法
                     */
                    one = @One(select = "com.itheima.one_to_one.PersonMapper.selectById")
            )
    })
    public abstract List<Card> selectAll();
}

一对一操作注解解析
@Results:封装映射关系的父注解

  • Result[] value():定义了 Result 数组

@Result:封装映射关系的子注解。

  • column 属性:查询出的表中字段名称
  • property 属性:实体对象中的属性名称
  • javaType 属性:被包含对象的数据类型
  • one 属性:一对一查询固定属性

@One:一对一查询的注解。

  • select 属性:指定调用某个接口中的方法

一对多操作

//StudentMapper接口
public interface StudentMapper {
   //根据cid查询student表
   @Select("SELECT * FROM student WHERE cid=#{cid}")
   public abstract List<Student> selectByCid(Integer cid);
}
//ClassesMapper接口
public interface ClassesMapper {
    //查询全部
    @Select("SELECT * FROM classes")
    @Results({
            @Result(column = "id",property = "id"),
            @Result(column = "name",property = "name"),
            @Result(
                    property = "students",  // 被包含对象的变量名
                    javaType = List.class,  // 被包含对象的实际数据类型
                    column = "id",          // 根据查询出的classes表的id字段来查询student表
                    /*
                        many、@Many 一对多查询的固定写法
                        select属性:指定调用哪个接口中的哪个查询方法
                     */
                    many = @Many(select = "com.itheima.one_to_many.StudentMapper.selectByCid")
            )
    })
    public abstract List<Classes> selectAll();
}

一对多操作注解解析
@Results:封装映射关系的父注解。

  • Result[] value():定义了 Result 数组

@Result:封装映射关系的子注解。

  • column 属性:查询出的表中字段名称
  • property 属性:实体对象中的属性名称
  • javaType 属性:被包含对象的数据类型
  • many 属性:一对多查询固定属性

@Many:一对多查询的注解。

  • select 属性:指定调用某个接口中的方法

多对多操作

//CourseMapper接口
public interface CourseMapper {
    //根据学生id查询所选课程
    @Select("SELECT c.id,c.name FROM stu_cr sc,course c WHERE sc.cid=c.id AND sc.sid=#{id}")
    public abstract List<Course> selectBySid(Integer id);
}
//StudentMapper接口
public interface StudentMapper {
    //查询全部
    @Select("SELECT DISTINCT s.id,s.name,s.age FROM student s,stu_cr sc WHERE sc.sid=s.id")
    @Results({
            @Result(column = "id",property = "id"),
            @Result(column = "name",property = "name"),
            @Result(column = "age",property = "age"),
            @Result(
                    property = "courses",   // 被包含对象的变量名
                    javaType = List.class,  // 被包含对象的实际数据类型
                    column = "id",          // 根据查询出student表的id来作为关联条件,去查询中间表和课程表
                    /*
                        many、@Many 一对多查询的固定写法
                        select属性:指定调用哪个接口中的哪个查询方法
                     */
                    many = @Many(select = "com.itheima.many_to_many.CourseMapper.selectBySid")
            )
    })
    public abstract List<Student> selectAll();
}

构建SQL语句

  • org.apache.ibatis.jdbc.SQL:构建 SQL 语句的功能类。通过一些方法来代替
  • SQL 语句的关键字。
    SELECT()
    FROM()
    WHERE()
    INSERT_INTO()
    VALUES()
    UPDATE()
    DELETE_FROM()
  • @SelectProvider:生成查询用的 SQL 语句注解。
  • @InsertProvider:生成新增用的 SQL 语句注解。
  • @UpdateProvider:生成修改用的 SQL 语句注解。
  • @DeleteProvider:生成删除用的 SQL 语句注解。
    type 属性:生成 SQL 语句功能类对象
    method 属性:指定调用方法

构建SQL语句中最为常用的是@SelectProvider;

以@SelectProvide为例代码演示

//1.构建SQL语句的生成类
public class sqlBuilder {
    public String findByNameAge(@Param("sname") String sname, @Param("age") Integer age) {
//此处1=1是为后面参数拼接更加规范,还有注意之间的空格
        StringBuffer sql = new StringBuffer("select * from student where 1=1");
        if (sname != null) {
            sql.append(" and sname = #{sname}");
        }
        if (age != null) {
            sql.append(" and age = #{age}");
        }
        return sql.toString();
    }
}

//2.使用@xxxprovider注释引入生成类
public interface StudentMapper {
    @SelectProvider(type = sqlBuilder.class, method = "findByNameAge")
    List<Student> findByNameAge(@Param("sname") String sname, @Param("age") Integer age);
}

//3.使用test类(这里使用了三层架构)
public class StudentTest {

    private StudentService studentService = new StudentServiceImpl();
    @Test
    public void testQueryByNameAndAge() {
        Student student = new Student(25, "小花", 18, new Date());
        List<Student> s = studentService.findByNameAge(null, student.getAge());
//执行后的SQL:select * from student where 1=1 and age = ?
        System.out.println(s);
    }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,907评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,987评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,298评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,586评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,633评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,488评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,275评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,176评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,619评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,819评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,932评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,655评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,265评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,871评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,994评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,095评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,884评论 2 354

推荐阅读更多精彩内容