MyBatis的一对一关联关系

400人浏览 / 0人评论

本文修订日期:2019年11月25日

SQL脚本

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

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


drop table if exists tb_card;

create table tb_card (
id int primary key auto_increment,
code varchar(18)
);

insert into tb_card(code) values ('432801198009191038');

drop table if exists tb_person;

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) peferences 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使用,所以card_id做成了唯一键约束。如此一来,当一个person使用了一个card之后,其他的person就不能使用该card了。

实体类

接下来,创建一个Card对象和一个Person对象分别映射tb_card和tb_person表。

package cn.mybatis.mydemo.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();
    }

    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 + "]";
    }

}


package cn.mybatis.mydemo.domain;

import java.io.Serializable;

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();
    }

    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 + "]";
    }

}
映射文件

人和身份证是一对一的关系,即一个人只有一个身份证。在Person类中定义了一个card属性,该属性是一个Card类型,用来映射一对一的关联关系,表示这个人的身份证。接下来是XML映射文件。



  
  
      select * from tb_card where id = #{id} 
  
  






    
    
        select * from tb_person where id = #{id}
    

    
    
        
        
        
        
        
        
        
    


在PersonMapper.xml中定义了一个,其根据id查询Person信息,由于Person类除了简单的属性id、name、sex和age之外,还有一个关联对象card,所以返回的是一个名为personMapper的resultMap。personMapper中使用了元素映射一对一的关联关系。其中,select属性表示会使用column属性的card_id值作为参数执行CardMapper中定义的selectCardById语句,查询对应的Card数据,查询出的数据将被封装到property表示的card对象当中。

映射接口

我们通常都是使用SqlSession对象调用insert,update,delete和select方法进行测试。实际上,Mybatis官方手册建议通过mapper接口的代理对象访问mybatis,该对象关联了SqlSession对象,开发者可以通过该对象直接调用方法操作数据库。

下面定义一个mapper接口对象,需要注意的是,mapper接口对象的类名必须和之前的XML文件中的mapper的namespace一致,而方法名和参数也必须和XML文件中的元素的id属性和parameterType属性一致。

package cn.mybatis.mydemo.mapper;

import cn.mybatis.mydemo.domain.Person;

public interface PersonMapper
{

    /**
     * 根据id查询Person,方法名和参数必须和XML文件中的元素的id属性和parameterType属性一致
     * */
    Person selectPersonById(Integer id);

}
测试类
public class App
{
    public static void main(String[] args) throws Exception
    {
        // 读取mybatis-config.xml文件
        InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");

        // 初始化mybatis,创建SqlSessionFactory类的实例
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        // 创建Session实例
        SqlSession session = sqlSessionFactory.openSession();

        Person p = session.selectOne("cn.mybatis.mydemo.mapper.PersonMapper.selectPersonById", 1);
        System.out.println(p);
        System.out.println(p.getCard().getCode());

        // 获得mapper接口的代理对象
        PersonMapper pm = session.getMapper(PersonMapper.class);
        // 直接调用接口的方法,查询id为1的Peson数据
        Person p2 = pm.selectPersonById(1);
        // 打印Peson对象
        System.out.println(p2);
        // 打印Person对象关联的Card对象
        System.out.println(p2.getCard());

        // 提交事务
        session.commit();
        // 关闭Session
        session.close();
    }
}

运行APP类的main方法,通过SqlSession的getMapper(Class type)方法获得mapper接口的代理对象PersonMapper,调用selectPersonByld方法时会执行PersonMapper.xml中元素中定义的sql语句。

全部评论

晴天下起了小雨
2017-10-01 18:00
很喜欢,果断关注了
wjmyly7336064
2017-10-01 18:00
相当实用,赞美了
橘大佬
2017-10-01 18:00
就是有些细节再到位点就好了…