目录
一. 映射关系 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;}@Overridepublic 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;}@Overridepublic 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 mapperPUBLIC "-//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 idencardWHERE 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 mapperPUBLIC "-//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 mapperPUBLIC "-//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;//一个宠物只能对应一个主人 Userprivate 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;}@Overridepublic 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 mapperPUBLIC "-//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 mapperPUBLIC "-//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进行可一个封装。
映射关系就是你在查询一个表的时候,其中的某个属性对应另外一个表的一条记录,或者多条记录。比如你在查询教师表中的某个教师的信息,同时根据这个教师的工号,你可以查到这个教师所教的班级,以及班级的学生等信息。