MyBatis 关联映射

客观世界中的对象很少有孤立存在的,例如班级,往往与班级的学生存在关联关系,如果 得到某个班级的实例,那么应该可以直接获取班级对应的全部学生。反过来,如果已经得到一 个学生的实例,那么也应该可以访问该学生对应的班级。这种实例之间的互相访问就是关联关系。

关联关系是面向对象分析、面向对象设计最重要的知识,MyBatis完全可以理解这种关联 关系,如果映射得当,MyBatis的关联映射将可以大大简化持久层数据的访问。关联关系大致有如下分类。

  1. 一对一
  2. 一对多
  3. 多对多

一对一

在实际项目开发中,经常存在一对一关系,比如一个人只能有一个身份证,一个身份证只 能给一个人使用,这就是一对一的关系。一对一关系推荐使用唯一主外键关联,即两张表使用 外键关联关系,由于是一对一关联,因此还需要给外键列增加unique唯一约束。下面我们就用一个简单示例来看看MyBatis怎么处理一对一关系。

首先,给之前创建的mybatis数据库创建两个表tb_card和tb_person,并插入测试数据。 SQL脚本如下:

`
 CREATE TABLE tb_card(
id INT PRIMARY KEY AUTO_INCREMENT,
CODE VARCHAR(18)
);

INSERT INTO tb_card(CODE) VALUES('432801198009191038');

CREATE TABLE tb_person(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(18),
sex VARCHAR(18),
age INT,
card_id INT UNIQUE,
FOREIGN KEY (card_id) REFERENCES tb_card(id)
);

INSERT INTO tb_person(NAME,sex,age,card_id) VALUES('jack','男',23,1)

`

tb_person表的card_id作为外键参照tb_card表的主键id,因为是一对一关系,: 即一个card只能让一个person使用,所以cardjd做成了唯一键约束。如此一来,| 当一个person使用了一个card之后,其他的person就不能使用该card 了。

代码如下:Card

`
        package org.fkit.domain;

import java.io.Serializable;

public class Card implements Serializable {

private static final long serialVersionUID = 1L;

private Integer id;  // 主键id
private String code; // 身份证编号

public Card() {
    super();
    // TODO Auto-generated constructor stub
}
public Integer getId() {
    return id;
}
public void setId(Integer id) {
    this.id = id;
}
public String getCode() {
    return code;
}
public void setCode(String code) {
    this.code = code;
}
@Override
public String toString() {
    return "Card [id=" + id + ", code=" + code + "]";
}



}

 `

代码如下:Person

`
   public class Person implements Serializable {

private static final long serialVersionUID = 1L;

private Integer id;  // 主键id
private String name; // 姓名
private String sex;  // 性别
private Integer age; // 年龄

// 人和身份证是一对一的关系,即一个人只有一个身份证
private Card card; 

public Person() {
    super();
    // TODO Auto-generated constructor stub
}

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 String getSex() {
    return sex;
}

public void setSex(String sex) {
    this.sex = sex;
}

public Integer getAge() {
    return age;
}

public void setAge(Integer age) {
    this.age = age;
}

public Card getCard() {
    return card;
}

public void setCard(Card card) {
    this.card = card;
}

@Override
public String toString() {
    return "Person [id=" + id + ", name=" + name + ", sex=" + sex
            + ", age=" + age + "]";
}

}

`

一对多

在实际项目开发中,一对多是非常常见的关系,比如,一个班级可以有多个学生,一个学 生只能属于一个班级,班级和学生是一对多的关系,而学生和班级是多对一的关系。数据库中 一对多关系通常使用主外键关联,外键列应该在多方,即多方维护关系。下面我们就用一个简单本例来看看MyBatis怎么处理一对多关系。

首先,给之前创建的mybatis数据库创建两个表tb_clazz和tb_student,并插入测试数据。 SQL脚本如下:

`
CREATE TABLE tb_clazz(
id INT PRIMARY KEY AUTO_INCREMENT,
CODE VARCHAR(18),
NAME VARCHAR(18)
);

INSERT INTO tb_clazz(CODE,NAME) VALUES('j1601','aaa');

CREATE TABLE tb_student(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(18),
sex VARCHAR(18),
age INT,
clazz_id INT,
FOREIGN KEY (clazz_id) REFERENCES tb_clazz(id)
);

INSERT INTO tb_student(NAME,sex,age,clazz_id) VALUES('jack','男',23,1);
INSERT INTO tb_student(NAME,sex,age,clazz_id) VALUES('rose','女',18,1);
INSERT INTO tb_student(NAME,sex,age,clazz_id) VALUES('tom','男',21,1);
INSERT INTO tb_student(NAME,sex,age,clazz_id) VALUES('alice','女',20,1);


`

tb_student表的clazz_id作为外键参 照tb_clazz表的主键id。

Clazz实体:

`
  public class Clazz implements Serializable {

private static final long serialVersionUID = 1L;

private Integer id; // 班级id,主键
private String code; // 班级编号
private String name; // 班级名称

// 班级和学生是一对多的关系,即一个班级可以有多个学生
private List<Student> students;

public Clazz() {
    super();
    // TODO Auto-generated constructor stub
}
public Integer getId() {
    return id;
}
public void setId(Integer id) {
    this.id = id;
}
public String getCode() {
    return code;
}
public void setCode(String code) {
    this.code = code;
}
public String getName() {
    return name;
}
public void setName(String name) {
    this.name = name;
}
public List<Student> getStudents() {
    return students;
}
public void setStudents(List<Student> students) {
    this.students = students;
}
@Override
public String toString() {
    return "Clazz [id=" + id + ", code=" + code + ", name=" + name + "]";
}




}


 
`

Student实体:

  `
   public class Student implements Serializable {

private static final long serialVersionUID = 1L;

private Integer id; // 学生id,主键
private String name; // 姓名
private String sex;  // 性别
private Integer age; // 年龄

// 学生和班级是多对一的关系,即一个学生只属于一个班级
private Clazz clazz;

public Student() {
    super();
    // TODO Auto-generated constructor stub
}

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 String getSex() {
    return sex;
}

public void setSex(String sex) {
    this.sex = sex;
}

public Integer getAge() {
    return age;
}

public void setAge(Integer age) {
    this.age = age;
}

public Clazz getClazz() {
    return clazz;
}

public void setClazz(Clazz clazz) {
    this.clazz = clazz;
}

@Override
public String toString() {
    return "Student [id=" + id + ", name=" + name + ", sex=" + sex
            + ", age=" + age + "]";
}


}

   `

多对多

在实际项目开发中,多对多关系也是非常常见的关系,比如,一个购物系统中,一个用户 可以有多个订单,这是一对多的关系;一个订单中可以购买多种商品,一种商品也可以属于多 个不同的订单,订单和商品就是多对多的关系。对于数据库中多对多关系建议使用一个中间表 来维护关系,中间表中的订单id作为外键参照订单表的id,商品id作为外键参照商品表的id。 下面我们就用一个简单示例来看看MyBatis怎么处理多对多关系。

首先,给之前创建的mybatis数据库创建三个表tb_user、tb_article和tb_order, 再创建一个中间表维护tb_article和tb_order的关系,并插入测试数据。SQL脚本如下。

`
/**
 * 
 CREATE TABLE tb_user(
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(18),
loginname VARCHAR(18),
PASSWORD VARCHAR(18),
phone VARCHAR(18),
address VARCHAR(18)
);

INSERT INTO tb_user(username,loginname,PASSWORD,phone,address)
VALUES('杰克','jack','123456','1392456789','广州');

CREATE TABLE tb_article(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(18),
price DOUBLE,
remark VARCHAR(18)
);

INSERT INTO tb_article(NAME,price,remark) 
VALUES('aaa',108.9,'aaa经典著作');
INSERT INTO tb_article(NAME,price,remark) 
VALUES('bbb',99.9,'bbb经典著作');
INSERT INTO tb_article(NAME,price,remark) 
VALUES('ccc',89.9,'ccc经典著作');
INSERT INTO tb_article(NAME,price,remark) 
VALUES('ddd',69.9,'ddd经典著作');


CREATE TABLE tb_order(
id INT PRIMARY KEY AUTO_INCREMENT,
CODE VARCHAR(32),
total DOUBLE,
user_id INT,
FOREIGN KEY (user_id) REFERENCES tb_user(id)
);

INSERT INTO tb_order(CODE,total,user_id)
VALUES('6aa3fa359ff14619b77fab5990940a2d',388.6,1);

INSERT INTO tb_order(CODE,total,user_id)
VALUES('6aa3fa359ff14619b77fab5990940b3c',217.8,1);

CREATE TABLE tb_item(
order_id INT,
article_id INT,
amount INT,
PRIMARY KEY(order_id,article_id),
FOREIGN KEY (order_id) REFERENCES tb_order(id),
FOREIGN KEY (article_id) REFERENCES tb_article(id)
);

INSERT INTO tb_item(order_id,article_id,amount) 
VALUES(1,1,1);
INSERT INTO tb_item(order_id,article_id,amount) 
VALUES(1,2,1);
INSERT INTO tb_item(order_id,article_id,amount) 
VALUES(1,3,2);

INSERT INTO tb_item(order_id,article_id,amount) 
VALUES(2,4,2);
INSERT INTO tb_item(order_id,article_id,amount) 
VALUES(2,1,1);

 * */``
`

实体:User

 `
 public class User implements Serializable{

private static final long serialVersionUID = 1L;

private Integer id;  // 用户id,主键
private String username;  // 用户名
private String loginname; // 登录名
private String password;  // 密码
private String phone;    // 联系电话
private String address;  // 收货地址

// 用户和订单是一对多的关系,即一个用户可以有多个订单
private List<Order> orders;

public User() {
    super();
    // TODO Auto-generated constructor stub
}

public User(String username, String loginname, String password,
        String phone, String address) {
    super();
    this.username = username;
    this.loginname = loginname;
    this.password = password;
    this.phone = phone;
    this.address = address;
}

public Integer getId() {
    return id;
}

public void setId(Integer id) {
    this.id = id;
}

public String getUsername() {
    return username;
}

public void setUsername(String username) {
    this.username = username;
}

public String getLoginname() {
    return loginname;
}

public void setLoginname(String loginname) {
    this.loginname = loginname;
}

public String getPassword() {
    return password;
}

public void setPassword(String password) {
    this.password = password;
}

public String getPhone() {
    return phone;
}

public void setPhone(String phone) {
    this.phone = phone;
}

public String getAddress() {
    return address;
}

public void setAddress(String address) {
    this.address = address;
}

public List<Order> getOrders() {
    return orders;
}

public void setOrders(List<Order> orders) {
    this.orders = orders;
}

@Override
public String toString() {
    return "User [id=" + id + ", username=" + username + ", loginname="
            + loginname + ", password=" + password + ", phone=" + phone
            + ", address=" + address + "]";
}


}

  `

实体:Order

`
 public class Order implements Serializable {

private static final long serialVersionUID = 1L;

private Integer id;  // 订单id,主键
private String code;  // 订单编号
private Double total; // 订单总金额

// 订单和用户是多对一的关系,即一个订单只属于一个用户
private User user;

// 订单和商品是多对多的关系,即一个订单可以包含多种商品
private List<Article> articles;

public Order() {
    super();
    // TODO Auto-generated constructor stub
}

public Order(String code, Double total) {
    super();
    this.code = code;
    this.total = total;
}

public Integer getId() {
    return id;
}

public void setId(Integer id) {
    this.id = id;
}

public String getCode() {
    return code;
}

public void setCode(String code) {
    this.code = code;
}

public Double getTotal() {
    return total;
}

public void setTotal(Double total) {
    this.total = total;
}

public User getUser() {
    return user;
}

public void setUser(User user) {
    this.user = user;
}

public List<Article> getArticles() {
    return articles;
}

public void setArticles(List<Article> articles) {
    this.articles = articles;
}

@Override
public String toString() {
    return "Order [id=" + id + ", code=" + code + ", total=" + total + "]";
}


}

`

实体:Article

`
  public class Article implements Serializable {

private static final long serialVersionUID = 1L;

private Integer id;     // 商品id,主键
private String name;    // 商品名称
private Double price;   // 商品价格
private String remark;  // 商品描述

// 商品和订单是多对多的关系,即一种商品可以包含在多个订单中
private List<Order> orders;

public Article() {
    super();
    // TODO Auto-generated constructor stub
}

public Article(String name, Double price, String remark) {
    super();
    this.name = name;
    this.price = price;
    this.remark = remark;
}

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 Double getPrice() {
    return price;
}

public void setPrice(Double price) {
    this.price = price;
}

public String getRemark() {
    return remark;
}

public void setRemark(String remark) {
    this.remark = remark;
}

public List<Order> getOrders() {
    return orders;
}

public void setOrders(List<Order> orders) {
    this.orders = orders;
}

@Override
public String toString() {
    return "Article [id=" + id + ", name=" + name + ", price=" + price
            + ", remark=" + remark + "]";
}

}


`

tb_order表的user_id作为外键参照tb_user表的主键id。tb_item表作为中间表, 用来维护tb_article和tb_order的多对多关系,tb_imte表的order_id作为外键参照 tb_order表的主键id, article id作为外键参照tb article表的主键id


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值