目录
一. 映射关系 1 对 1-映射方式
1.通过xml文件实现映射的一对一关系
总结 :
2.通过注解的方式来实现下面的 1 对 1 的映射关系,实现级联查询
总结:
二. 映射关系多对一
1.通过xml文件实现映射的多对一关系
2.通过注解的方式来实现下面的 多对一 的映射关系,实现级联查询
XML与注解的形式本质都是以XML的形式进行的,只不过注解对XML进行可一个封装。
映射关系就是你在查询一个表的时候,其中的某个属性对应另外一个表的一条记录,或者多条记录。比如你在查询教师表中的某个教师的信息,同时根据这个教师的工号,你可以查到这个教师所教的班级,以及班级的学生等信息。
一. 映射关系 1 对 1-映射方式
1.通过xml文件实现映射的一对一关系
1. 创建 person 表和 idencard 表
CREATE TABLE person(id INT PRIMARY KEY AUTO_INCREMENT,NAME VARCHAR(32) NOT NULL DEFAULT '',card_id INT ,FOREIGN KEY (card_id) REFERENCES idencard(id))CHARSET utf8;
CREATE TABLE idencard(id INT PRIMARY KEY AUTO_INCREMENT,card_sn VARCHAR(32) NOT NULL DEFAULT '')CHARSET utf8 ;INSERT INTO idencard VALUES(1,'5002262001121212');
INSERT INTO person VALUES(1,'长离',1);
SELECT * FROM person;
SELECT * FROM idencard
3.创建IdenCard类
package com.sn.entity;
/**
* @author sn
*/
public class IdenCard {
private Integer id;
private String card_sn;
public IdenCard() {
}
public IdenCard(Integer id, String card_sn) {
this.id = id;
this.card_sn = card_sn;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getCard_sn() {
return card_sn;
}
public void setCard_sn(String card_sn) {
this.card_sn = card_sn;
}
@Override
public String toString() {
return "IdenCard{" +
"id=" + id +
", card_sn='" + card_sn + '\'' +
'}';
}
}
4.创建Person类
package com.sn.entity;
/**
* @author sn
*/
public class Person {
private Integer id;
private String name;
private IdenCard card;
public Person() {
}
public Person(Integer id, String name, IdenCard card) {
this.id = id;
this.name = name;
this.card = card;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public IdenCard getCard() {
return card;
}
public void setCard(IdenCard card) {
this.card = card;
}
@Override
public String toString() {
return "Person{" +
"id=" + id +
", name='" + name + '\'' +
", card=" + card +
'}';
}
}
5.创建IdenCardMapper接口
package com.sn.mapper;
import com.sn.entity.IdenCard;
/**
* @author sn
*/
public interface IdenCardMapper {
//根据 id 获取到身份证
public IdenCard getIdenCardById(Integer id);
}
6.创建IdenCardMapper.xml映射文件
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.sn.mapper.IdenCardMapper">
<!-- 实现 getIdenCardById -->
<select id="getIdenCardById" resultType="IdenCard" parameterType="Integer">
SELECT * FROM idencard
WHERE id=#{id}
</select>
</mapper>
7.创建PersonMapper接口
package com.sn.mapper;
import com.sn.entity.Person;
/**
* @author sn
*/
public interface PersonMapper {
//通过 Person 的 id 获取到 Person,包括这个 Person 关联的 IdenCard 对象
public Person getPersonById(Integer id);
}
8.创建PersonMapper.xml文件
1.写xml用association的第一种方式
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.sn.mapper.PersonMapper">
<!-- 实现 getPersonById [方式 1] -->
<!-- 定义一个 resultMap 来映射返回的结果 -->
<resultMap type="Person" id="personResultMap">
<!-- id: 一个 ID 结果;标记出作为 ID 的结果可以帮助提高整体性能, 通常指定主
键
property="id" 表示 person 对象的哪个属性代表主键
column="id" 表示对应的表的字段 -->
<id property="id" column="id"/>
<result property="name" column="name"/>
<!-- association: 一个复杂类型的关联 -->
<!-- javaType:返回的java的类型
-->
<association property="card" javaType="com.sn.entity.IdenCard">
<!-- 将关联的 card 对象哪些属性放入到这个 resultMap -->
<result property="id" column="id"/>
<result property="card_sn" column="card_sn"/>
</association>
</resultMap>
<select id="getPersonById" parameterType="Integer" resultMap="personResultMap">
select * from person , idencard WHERE person.id=#{id}
AND person.card_id = idencard.id;
</select>
</mapper>
2.用xml中association的第二种方式
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.sn.mapper.PersonMapper">
<!-- 实现 getPersonById [方式 2] -->
<!-- 定义一个 resultMap 来映射返回的结果 -->
<resultMap type="Person" id="personResultMap2">
<!-- id: 一个 ID 结果;标记出作为 ID 的结果可以帮助提高整体性能, 通常指定主
键
property="id" 表示 person 对象的哪个属性代表主键
column="id" 表示对应的表的字段 -->
<id property="id" column="id"/>
<result property="name" column="name"/>
<!-- association: 一个复杂类型的关联 -->
<association property="card" column="card_id"
select="com.sn.mapper.IdenCardMapper.getIdenCardById"/>
</resultMap>
<select id="getPersonById2" parameterType="Integer" resultMap="personResultMap2">
select * from person where id = #{id}
</select>
</mapper>
测试结果:
查询的结果::
总结 :
上面上述案例就是:多表查询,就是当我们查询一个表的一条记录的时候,其中的某个属性是另外一个表的主键(也就是可以标识一条记录的属性)。也就是外键约束!
当我们实现一对一的映射的时候,想要使返回的结果如上图所示,就必须用resultMap进行结果的映射。
当我们在XML文件进行方法的实现的时候,mybatis框架会根据方法中的结果映射,返回出你所想要的结果。这里的一对一的映射,就是平常大学老师教的方法,同时这里涉及到了级联查询(也就是所说的多表查询)
2.通过注解的方式来实现下面的 1 对 1 的映射关系,实现级联查询
1.创建IdenCardMapperAnnotaion
package com.sn.mapper;
import com.sn.entity.IdenCard;
import org.apache.ibatis.annotations.Select;
/**
* @author sn
*/
public interface IdenCardMapperAnnotaion {
//根据 id 获取到身份证
//这个方法不需要返回任何级联对象
@Select("SELECT * FROM idencard WHERE id=#{id}")
public IdenCard getIdenCardById(Integer id);
}
2.创建 PersonMapperAnnotatio
package com.sn.mapper;
import com.sn.entity.Person;
import org.apache.ibatis.annotations.One;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
/**
* @author sn
*/
public interface PersonMapperAnnotation {
//通过 Person 的 id 获取到 Person,包括这个 Person 关联的 IdenCard 对象
//想:你到底返回什么结果,然后你想办法给他
/*
* private Integer id;
private String name;
private IdenCard card;
*/
@Select("select * from person WHERE id=#{id}")
@Results({
@Result(id = true, property = "id", column = "id"),
@Result(property = "name", column = "name"),
@Result(property = "card", column = "card_id",
one = @One(select =
"com.sn.mapper.IdenCardMapperAnnotaion.getIdenCardById"))
})
public Person getPersonById(Integer id);
}
查询的结果::
运行的结果也和之前是一样的,用动态代理的方式
总结:
二. 映射关系多对一
1.通过xml文件实现映射的多对一关系
CREATE TABLE mybatis_user
(id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(32) NOT NULL DEFAULT '' )CHARSET=utf8 ;CREATE TABLE mybatis_pet
(id INT PRIMARY KEY AUTO_INCREMENT,
nickname VARCHAR(32) NOT NULL DEFAULT '',
user_id INT ,
FOREIGN KEY (user_id) REFERENCES mybatis_user(id)
)CHARSET=utf8 ;INSERT INTO mybatis_user
VALUES(NULL,'宋江'),(NULL,'张飞');
INSERT INTO mybatis_pet
VALUES(1,'黑背',1),(2,'小哈',1);
INSERT INTO mybatis_pet
VALUES(3,'波斯猫',2),(4,'贵妃猫',2);SELECT * FROM mybatis_user;
SELECT * FROM mybatis_pet;
2.创建User类
package com.sn.entity;
import java.util.List;
/**
* @author sn
*/
public class User {
private Integer id;
private String name;
//一个用户可以对应多个宠物
private List<Pet> pets;
public User() {
}
public User(Integer id, String name, List<Pet> pets) {
this.id = id;
this.name = name;
this.pets = pets;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Pet> getPets() {
return pets;
}
public void setPets(List<Pet> pets) {
this.pets = pets;
}
}
3创建Pet类
package com.sn.entity;
/**
* @author sn
*/
public class Pet {
private Integer id;
private String nickname;
//一个宠物只能对应一个主人 User
private User user;
public Pet() {
}
public Pet(Integer id, String nickname, User user) {
this.id = id;
this.nickname = nickname;
this.user = user;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
@Override
public String toString() {
return "Pet{" +
"id=" + id +
", nickname='" + nickname + '\'' +
'}';
}
}
public interface PetMapper {// 通过 User 的 id 来获取 pet 对象,可能有多个,因此使用 List 接收public List < Pet > getPetByUserId ( Integer userId);// 通过 pet 的 id 获取 Pet 对象public Pet getPetById ( Integer id);}
public interface UserMapper {// 通过 id 获取 User 对象public User getUserById ( Integer id);}
4. 创建 UserMapper.xml
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.sn.mapper.UserMapper">
<resultMap type="com.sn.entity.Pet" id="PetResultMap">
<id property="id" column="id"/>
<result property="nickname" column="nickname"/>
<association property="user" column="user_id" select="com.sn.mapper.PetMapper.getUserById"></association>
</resultMap>
<!-- :
1. user_id=#{userId} userId 就是调用 getPetByUserId 传入的用户 id
2. userId 名称,由程序员来确定,比如你写成 id,uId 等都可以-->
<select id="getPetByUserId" parameterType="Integer" resultMap="PetResultMap">
select * from mybatis_pet where user_id=#{userId}
</select>
<select id="getPetById" parameterType="Integer" resultMap="PetResultMap">
select * from mybatis_pet where id=#{id}
</select>
</mapper>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.sn.mapper.PetMapper">
<!-- collection : 一对多关联查询, 表示一个用户可能对应多个 pet 对象
ofType: 集合中元素对象的类型 -->
<resultMap type="com.sn.entity.User" id="UserResultMap">
<id property="id" column="id"/>
<result property="name" column="name"/>
<!-- column="id" 就是当前 User 表的主键字段名,通过这个 user 的 id,
去查询对应的 pet 有哪些 -->
<collection property="pets" ofType="com.sn.entity.Pet" column="id"
select="com.sn.mapper.UserMapper.getPetByUserId"></collection>
</resultMap>
<select id="getUserById" parameterType="Integer" resultMap="UserResultMap">
select * from mybatis_user where id=#{id};
</select>
</mapper>
那么问题来了?有人会问那如果这个方法的参数有多个怎么办呢?
: 在数据库库中表和表的联系可以通过外键约束进行,也就是一个表的非主属性,对应的是另外一个表的主键,而表的主键只有一个(主键就是可以唯一标识一条记录的属性字段)。所以为啥只有一个参数了。
2.通过注解的方式来实现下面的 多对一 的映射关系,实现级联查询
1.UserMapperAnnotation 接口
package com.sn.mapper;
import com.sn.entity.User;
import org.apache.ibatis.annotations.Many;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
/**
* @author sn
*/
public interface UserMapperAnnotation {
//通过 user 的 id 号,返回该用户的方法
@Select("select * from mybatis_user where id=#{id}")
@Results({
@Result(id=true,property="id",column="id"),
@Result(property="name",column="name"),
@Result(property="pets",column="id",
many=@Many(select="com.sn.mapper.PetMapperAnnotation.getPetByUserId"))
})
public User getUserById(Integer id);
}
2.PetMapperAnnotation接口
package com.sn.mapper;
import com.sn.entity.Pet;
import org.apache.ibatis.annotations.One;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import java.util.List;
/**
* @author sn
*/
public interface PetMapperAnnotation {
//通过 User 的 id 来获取 pet 对象,可能有多个,因此使用 List 接收
@Select("select * from mybatis_pet where user_id=#{userId}")
@Results({
@Result(id = true, property = "id", column = "id"),
@Result(property = "nickname", column = "nickname")
})
public List<Pet> getPetByUserId(Integer userId);
//通过 pet 的 id 获取 Pet 对象
@Select("select id AS tnId,nickname AS tnNickname, user_id AS tnUser_id from mybatis_pet where id=#{id}")
@Results({
@Result(id = true, property = "id", column = "tnId"),
@Result(property = "nickname", column = "tnNickname"),
@Result(property = "user", column = "tnUser_id",
one = @One(select =
"com.sn.mapper.UserMapperAnnotation.getUserById"))
})
public Pet getPetById(Integer id);
}
XML与注解的形式本质都是以XML的形式进行的,只不过注解对XML进行可一个封装。
映射关系就是你在查询一个表的时候,其中的某个属性对应另外一个表的一条记录,或者多条记录。比如你在查询教师表中的某个教师的信息,同时根据这个教师的工号,你可以查到这个教师所教的班级,以及班级的学生等信息。