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)
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和方式一的注解
-
注意点
1.@Select注解就相当于<select>标签
2.@Results就是<resultMap>标签
3.@Result就是<result>标签
4.@Result(id=true)就是<id>标签
- 方式二的xml和方式二的注解
- 注意点
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图
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形式和注解形式的图对比
- 注意点
注解和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图
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形式和注解形式的图对比
来自:虽然帅,但是菜的cxy
创作不易,来点鼓励,点赞,评论,转发是我最大的动力