mybatis基于注解开发【三】

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Bz3WjWQO-1597936286931)(C:\Users\wzj\AppData\Roaming\Typora\typora-user-images\1597933261672.png)]

Mybatis的常用注解
@Insert@Delete@Update@Select@Results@Result@One@Many

使用注解的好处,不用写映射文件了。什么参数类型,返回值类型等。

mybatis基于注解开发
1.1:一对一(丈夫和妻子)

1、创建表

create table wife(
	wid int primary key auto_increment,
	wname varchar(20)
);
insert into wife values(null,'西施');
insert into wife values(null,'妲己');

create table husband(
	hid int primary key,
	hname varchar(20),
  constraint fk_husband_wife foreign key(hid) references wife(wid) 
);
insert into husband values(1,'张三');
insert into husband values(3,'李四');
  • E-R图(使用navicat)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aDNk4UPP-1597936286933)(C:\Users\wzj\AppData\Roaming\Typora\typora-user-images\1597933726575.png)]

2、创建实体

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Wife {
    private Integer id;
    private String name;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Husband {
    private Integer id;
    private String name;
    /*一个丈夫只有一个合法的妻子*/
    private Wife wife;
}

3、Mapper接口

public interface WifeMapper {
    Wife findById(Serializable id);
}
public interface HusbandMapper {

    Husband findById(Serializable id);
}
1.1.1:基于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.wzj.mapper.HusbandMapper">

    <resultMap id="husbandMap" type="com.wzj.domain.Husband">
        <id column="hid" property="id"></id>
        <result column="hname" property="name"></result>
        <result column="wid" property="wife.id"></result>
        <result column="wname" property="wife.name"></result>
    </resultMap>

    <!-- Husband findById(Serializable id);-->
    <select id="findById" resultMap="husbandMap">
        select
            h.hid, h.hname, w.wid, w.wname
        from
            husband h
        inner join
            wife w
        on
            h.hid = w.wid
        where
            h.hid = #{hid}
    </select>
</mapper>

只针对一对一可以这样!!!,但好像不怎么常用

  • 方式二:【推荐】
<?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.wzj.mapper.HusbandMapper">

    <resultMap id="husbandMap" type="com.wzj.domain.Husband">
        <id column="hid" property="id"></id>
        <result column="hname" property="name"></result>
        <association property="wife" javaType="com.wzj.domain.Wife">
            <id column="wid" property="id"></id>
            <result column="wname" property="name"></result>
        </association>
    </resultMap>

    <!-- Husband findById(Serializable id);-->
    <select id="findById" resultMap="husbandMap">
        select
            h.hid, h.hname, w.wid, w.wname
        from
            husband h
        inner join
            wife w
        on
            h.hid = w.wid
        where
            h.hid = #{hid}
    </select>
</mapper>

注:加载映射文件

<mappers>
    <!--使用xml的方式-->
    <mapper resource="\com.wzj.mapper\PersonMapper.xml"></mapper>
</mappers>
1.1.2:基于注解一对一
  • 方式一:【对应xml方式一】
public interface HusbandMapper {

    /**
     * 一次性查询出来,然后挨个赋值即可
     */
    @Select("SELECT h.hid, h.hname, w.wid, w.wname FROM husband h INNER JOIN wife w ON h.hid = w.wid WHERE h.hid = #{id}")
    @Results({
            @Result(id = true, column = "hid", property = "id"),
            @Result(column = "hname", property = "name"),
            @Result(column = "wid", property = "wife.id"),
            @Result(column = "wname", property = "wife.name")
    })
    Husband findById(Serializable id);
    
}
  • 方式二:【对应xml方式二】
public interface HusbandMapper {

    /*注解方式*/
    /**
     * 分两步查
     * select * from husband where hid = 1;
     * select * from wife where wid = 1;
     */
    @Select("select * from husband where hid = #{id}")
    @Results({
            @Result(id = true, column = "hid", property = "id"),
            @Result(column = "hname", property = "name"),
            @Result(
                    property = "wife",
                    javaType = Wife.class,
                    column = "hid",
                    one = @One(select = "com.wzj.mapper.WifeMapper.findById")
            ),
    })
    Husband findById(Serializable id);
}
public interface WifeMapper {

    //因为查询出来的列名和实体类的属性名不一致,所以需要手动的去映射一下
    @Select("select * from wife where wid = #{id}")
    @Results({
            @Result(id = true, column = "wid", property = "id"),
            @Result(column = "wname", property = "name"),
    })
    Wife findById(Serializable id);
}

注:加载映射文件

<mappers>
    <package name="com.wzj.mapper"/>
</mappers>
1.1.3:xml形式和注解形式的图对比
  • 方式一的xml和方式一的注解
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-a1f3g93o-1597936286935)(C:\Users\wzj\AppData\Roaming\Typora\typora-user-images\1597934562570.png)]

  • 注意点

1.@Select注解就相当于<select>标签
2.@Results就是<resultMap>标签
3.@Result就是<result>标签
4.@Result(id=true)就是<id>标签
  • 方式二的xml和方式二的注解

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E5Cy7l8A-1597936286937)(C:\Users\wzj\AppData\Roaming\Typora\typora-user-images\1597935061862.png)]

  • 注意点
1.注解中只有javaType,没有ofType,而且是“属性类型”的字节码对象
例子: private List<User> users,那么javaType = List.class,而不是User.class!!!
2.这里的hid是从@Select注解中查询出来的值,准备给@One注解指定的方法传递的参数!!
3.@one就代表<association>标签
1.2:一对多(部门和员工)

1、创建表

## 一个部门有多个员工,一个员工只属于一个部门,多方是从表,一方是主表,一般先创建主表,再创建从表
create table dept(
	did int auto_increment primary key,
	dname varchar(20) not null,
	loc varchar(20) not null
);
insert into dept() values(1,'技术部','深圳'),(2,'财务部','北京');

create table emp(
	eid int auto_increment primary key,
	ename varchar(20) not null,
	did int,
	constraint dept_emp_fk foreign key(did) references dept(did)
);
insert into emp() values(1,'wzj',1),(2,'sbt',1),(3,'dyt',2);

  • E-R图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-69UMf1h5-1597936286938)(C:\Users\wzj\AppData\Roaming\Typora\typora-user-images\1597933814340.png)]

2、实体类(描述关系)

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Dept {
    private Integer id;
    private String name;
    private String loc;
    /*一个部门有多个员工*/
    private List<Emp> emps;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Emp {
    private Integer id;
    private String name;
    /*一个员工只属于一个部门*/
    private Dept dept;
}

3、Mapper接口

public interface DeptMapper {

    /*查询部门及其部门下的员工信息*/
    Dept findById(Serializable id);
}
public interface EmpMapper {
}
1.2.1:基于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.wzj.mapper.DeptMapper">
    
    <resultMap id="deptMap" type="com.wzj.domain.Dept">
        <id column="did" property="id"></id>
        <result column="dname" property="name"></result>
        <result column="loc" property="loc"></result>
        <collection property="emps" ofType="com.wzj.domain.Emp">
            <id column="eid" property="id"></id>
            <result column="ename" property="name"></result>
        </collection>
    </resultMap>
    
    <!--Dept findById(Serializable id);-->
    <select id="findById" resultMap="deptMap">
        select
            d.did, d.dname, d.loc, e.eid, e.ename
        from
            dept d
        inner join
            emp e
        on
            e.did = d.did
        where
            d.did = #{id}
    </select>

</mapper>

1.2.2:基于注解的一对多

不需要写映射文件,但也需要在mybatis核心配置文件中配置<mappers>标签

public interface DeptMapper {

    /*查询部门及其部门下的员工信息*/
    @Select("select * from dept where did = #{id}")
    @Results({
            @Result(id = true, column = "did", property = "id"),
            @Result(column = "dname", property = "name"),
            @Result(column = "loc", property = "loc"),
            @Result(
                    column = "did", //这个注意一定要写:表示将上一条中的select语句查询的did, 作为参数传递给下一个select语句!
                    property = "emps",
                    javaType = List.class,
                    many = @Many(select = "com.wzj.mapper.EmpMapper.findByForeignKey")
            )
    })
    Dept findById(Serializable id);
}
public interface EmpMapper {

    @Select("select * from emp where did = #{did}")
    @Results({
            @Result(id = true, column = "eid", property = "id"),
            @Result(id = true, column = "ename", property = "name")
    })
    List<Emp> findByForeignKey(Serializable id);
}
1.2.3:xml形式和注解形式的图对比

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rpRX7ZTC-1597936286939)(C:\Users\wzj\AppData\Roaming\Typora\typora-user-images\1597935522588.png)]

  • 注意点
注解和xml中的javaType的区别!!
一:
在注解中@Result只有javaType属性,没有ofType属性!!!
在注解中javaType就是该属性的类型的字节码对象
例子:
一对一: private Dept dept; 这时javaType就是Dept.class
一对多: private List<Emp> emps; 这时javaType就是List.class, 而不是该集合中的泛型类型

二:
在xml中javaType是association标签(表示一对一)的属性,它的属性值是属性类型的类的限定名
例子:private Wife wife; 这时javaType就是com.wzj.domain.Wife
在xml中ofType是collection标签(表示一对多)的属性,它的属性值是属性类型的泛型类的限定名
例子: private List<Emp> emps; 这时的ofType就是com.wzj.domain.Emp
  • 遇到的异常
1.大概是写懵了,才会出现这个异常 哈哈哈,写到吐才证明功夫到家了
mybatis Cause: java.lang.IllegalArgumentException: argument type mismatch原因
在一对多类型中,使用标签错误,应该使用collection标签
1.3:多对多(学生和老师)

1.创建表

-- 多对多需要使用第三张表,也就是中间表,
create table teacher(
	tid int primary key,
    tname varchar(20)
);
insert into teacher(tid,tname) values(1,'王老师');
insert into teacher(tid,tname) values(2,'张老师');
insert into teacher(tid,tname) values(3,'李老师');
 
create table student(
	sid int primary key,
    sname varchar(20)
); 
insert into student(sid,sname) values(1,'马云同学');
insert into student(sid,sname) values(2,'马化腾同学');
insert into student(sid,sname) values(3,'乔布斯同学');

create table stu_teach(
	sid int,
	tid int,
	constraint fk_student foreign key(sid) references student(sid),
	constraint fk_teacher foreign key(tid) references teacher(tid)
);
insert into stu_teach(sid,tid) values(1,1);
insert into stu_teach(sid,tid) values(1,2);
insert into stu_teach(sid,tid) values(1,3);
insert into stu_teach(sid,tid) values(2,3);
  • E-R图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RHb7VI6k-1597936286940)(C:\Users\wzj\AppData\Roaming\Typora\typora-user-images\1597933882522.png)]

2、创建实体类,描述关系

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {
    private Integer id;
    private String name;
    /*一个学生有多个老师*/
    private List<Teacher> teachers;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Teacher {
    private Integer id;
    private String name;
    /*一个老师也有多个学生*/
    private List<Student> students;
}

3、Mapper接口

public interface StudentMapper {

    /*查询学生信息及其对应的老师信息*/
    Student findById(Serializable id);
}
public interface TeacherMapper {
    Student findById(Serializable id);
}
1.3.1:基于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.wzj.mapper.StudentMapper">

    <resultMap id="StudentMap" type="com.wzj.domain.Student">
        <id column="sid" property="id"></id>
        <result column="sname" property="name"></result>
        <collection property="teachers" ofType="com.wzj.domain.Teacher">
            <id column="tid" property="id"></id>
            <result column="tname" property="name"></result>
        </collection>
    </resultMap>

    <!--Student findById(Serializable id);-->
    <select id="findById" resultMap="StudentMap">
        select
            s.sid, s.sname, t.tid, t.tname
        from
            student s
        inner join
            stu_teach st
        on
            st.sid = s.sid
        inner join
            teacher t
        on
            st.tid = t.tid
        where
            s.sid = #{id}
    </select>

</mapper>
1.3.2:基于注解的多对多
public interface StudentMapper {

    /*查询学生信息及其对应的老师信息*/
    @Select("select * from student where sid = #{id}")
    @Results({
            @Result(id = true, column = "sid", property = "id"),
            @Result(column = "sname", property = "name"),
            @Result(
                    property = "teachers",
                    javaType = List.class,
                    column = "sid",
                    many = @Many(select = "com.wzj.mapper.TeacherMapper.findById")
            )
    })
    Student findById(Serializable id);
}
public interface TeacherMapper {

    @Select("SELECT * FROM stu_teach st INNER JOIN teacher t ON st.tid = t.tid WHERE st.sid = #{id}")
    @Results({
        @Result(id = true, column = "tid", property = "id"),
        @Result(column = "tname", property = "name")
    })
    Teacher findById(Serializable id);
}
第一句:在StudentMapper中
select * from student where sid = 1

第二句:在TeacherMapper中
select
	*
from 
	stu_teach st
inner join
	teacher t 
on
	st.tid = t.tid
where
  st.sid = 1

注:第二句中的sid值,就是第一句传递过来的
1.3.3:xml形式和注解形式的图对比

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cI5WC8Di-1597936286940)(C:\Users\wzj\AppData\Roaming\Typora\typora-user-images\1597935741361.png)]
来自:虽然帅,但是菜的cxy
创作不易,来点鼓励,点赞,评论,转发是我最大的动力

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值