Mybatis-05:注解开发及多表模型操作

5.1. 注解开发

采用注解开发可不用创建映射配置文件,直接在执行SQL语句的接口内使用注解即可。操作步骤如下:

  • 在核心配置文件中引入接口类:

<mappers>
    <!-- 接口类所在包 -->
    <package name="com.itheima.mapper"/>
</mappers>
  • 增删改查操作如下:

//直接在接口类中的增删改查方法上添加注解。格式即如下所示。
public interface StudentMapper {
    @Select("SELECT * FROM student")
    public abstract List<Student> selectAll();

    @Insert("INSERT INTO student VALUES(#{id}, #{name}, #{age})")
    public abstract Integer insert(Student stu);

    @Update("UPDATE student SET age = #{age} WHERE id=#{id}")
    public abstract Integer update(Student stu);

    @Delete("DELETE FROM student WHERE id=#{id}")
    public abstract Integer delete(Integer id);
}

//在测试类中
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);//加载mapper文件
Student stu = new Student(9,"生活呀",100);
//插入数据
Integer result = mapper.insert(stu);
System.out.println(result);

5.2. 多表模型操作:

5.2.1. 基本介绍:

  • 一对一:在任意一方建立外键,关联对方主键;

  • 一对多:在多的一方建立外键,关联一方主键;

  • 多对多:借助中间表,中间表至少两个字段,分别关联两张表的主键;

5.2.2. 一对一

一对一通常涉及两张表,例如:银行卡 {id,number,pid} 与 持卡人p {id,name,age}。在查询时会涉及两张表。

  • 创建映射配置文件:此时不能直接用<select>,而是需要如下的<resultMap>。

<mapper namespace="com.itheima.table01.OneToOneTest">
    <!--配置字段和实体对象之间的映射关系-->
    <!--id:唯一标识,type:所需赋值的对象名-->
    <resultMap id="oneToOne" type="card"> 
        
        <!--id标签:主键,column:SQL查询的列名,property:对象的属性名-->   
        <id column="cid" property="id"/>  
        
        <!--result标签:非主键,SQL其他查询列-->  
        <result column="number" property="number"/>    
        
        <!--association:card下包含的其他对象,也要依次赋值,javaType:被包含对象的数据类型。-->
        <association property="p" javaType="person"> 
            <id column="pid" property="id"/>
            <result column="NAME" property="name"/>
            <result column="age" property="age"/>
        </association>
    </resultMap>

    <!-- SQL语句,查询结果类型通过resultMap赋值给对象的各个属性 -->
    <select id="selectAll" resultMap="oneToOne">
        SELECT c.id cid, number, pid, NAME, age FROM card c, person p WHERE c.pid = p.id
    </select>
</mapper>

5.2.3. 一对多

  • 具体步骤可参考上文,唯一区别是将<association>换为<collection>。

<resultMap id="OneToMany" type="classes">
        <id column="cid" property="id"/>
        <result column="cname" property="name"/>
        
        <!-- collection:对象中包含List对象时,例如班级中包含多个学生。 -->
        <collection property="students" ofType="student">
            <id column="sid" property="id"/>
            <result column="sname" property="name"/>
            <result column="sage" property="age"/>
        </collection>
</resultMap>
  • 多对多处理方式可参考一对多。

5.2.4. 注解一对一

在核心配置文件中加载类包,如上所示。由于一对一涉及两张表,因此对每个表均要设置一个查询接口。

  • 对于Person表的接口,创建的注释如下所示:

@Select("SELECT * FROM student WHERE id=#{id}")
public abstract Person selectById(Integer id);
  • 对于Card表中的接口,由于其中包含Person属性,故创建注释如下:

@Select("SELECT * FROM card")
//属性是一个Result数组
@Results({    
    //对属性赋值 
    @Result(column = "id", property = "id"),    
    @Result(column = "number", property = "number"),    
    //通过外键查询Person值
    @Result(property = "p", javaType = Person.class, column = "pid", 
              //one 特指一对一情况。其中select需要定位到具体方法名。且要求方法提供了查询注解,如上。
              one = @One(select = "com.itheima.one_to_one.PersonMapper.selectById")
    )
})
public abstract List<Card> selectAll();

5.2.5. 注解一对多

  • 在核心配置文件中加载多个类时,可直接加载项目包:

<mappers>
    <package name="com.itheima"/>
</mappers>
  • 同样涉及多张表,对于被包含的对象也要单独设置一个注解查询接口,本案例中设计classes与student,classes包含List <student>。

//在StudentMapper中,设置查询接口
public interface StudentMapper {
    @Select("SELECT * FROM student WHERE cid=#{cid}")
    public abstract Student selectByCid(Integer cid);
}
  • 在Classes中:

//在Classes接口中,使用many = @Many进行多对多查询。
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",            //用班级表中的id,作为student表的查询条件。
                    many = @Many(select = "com.itheima.one_to_many.StudentMapper.selectByCid")
            )
    })
    public abstract List<Classes> selectAll();
}

5.2.6. 注解多对多

多对多与一对多格式是一致的,只要搞清楚SQL语句的逻辑就可。

  • 在本案例中学生表student和课程表course分别是多对多的关系,并通过中间表stu_cr关联。

  • 在CourseMapper中:

public interface CourseMapper {
    @Select("SELECT c.id, c.name FROM stu_cr sc, course c 
             WHERE sc.sid = #{id} AND sc.cid = c.id")
    public abstract List<Course> selectById(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",
                    many = @Many(select = "com.itheima.many_to_many.CourseMapper.selectById")
            )
    })
    public abstract List<Student> selectAll();
}

5.3. 构建SQL语句功能类

5.3.1. 单独创建SQL生成类

  • 具体示例如下:

public class ReturnSql {
    //查询类,返回查询SQL语句
    public String getSelectAll(){
        return new SQL(){{ SELECT("*"); FROM("student");}}.toString();
    }
    
    //插入类,返回插入SQL语句
    public String getInsert(Student stu){
        return new SQL(){{ INSERT_INTO("student");
                            INTO_VALUES("#{id}, #{name}, #{age}");}}.toString();
    }
    
    //更新类,返回更新SQL语句
    public String getUpdate(Student stu){
        return new SQL(){{UPDATE("student");
                           SET("age=#{age}");
                           WHERE("id=#{id}"); }}.toString();
    }

    //删除类,返回删除SQL语句
    public String getDelete(Integer id){
        return new SQL(){{DELETE_FROM("student");
                           WHERE("id = #{id}"); }}.toString();
    }
}

5.3.2. 接口类

  • 接口类注解开发需要使用全新注解形式:

public interface StudentMapper {
    //需要使用带有Provider的注解进行开发。
    //其中type=上述SQL生成类。method=SQL生成类中所使用的方法名。
    @SelectProvider(type = ReturnSql.class, method = "getSelectAll")
    public abstract List<Student> selectAll();

    @InsertProvider(type = ReturnSql.class, method = "getInsert")
    public abstract Integer insert(Student stu);

    @UpdateProvider(type = ReturnSql.class, method = "getUpdate")
    public abstract Integer update(Student stu);

    @DeleteProvider(type = ReturnSql.class, method = "getDelete")
    public abstract Integer delete(Integer id);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值