MyBatis 关联查询的实现:一对一

不问归期 提交于 2020-11-19 02:28:52

 

有2个实体:用户、会员卡,一个用户只能办理一张会员卡,即一对一。

 

user_tb : 

 需要在一方引入另一方的主键作为外键。

 

 

card_tb:

 

 


 

 

使用扩展类

(1)在pojo包下新建User类:

package com.chy.pojo;

public class User {
    private Integer id;  //主键
    private String name;  //姓名
    private String tel;  //手机号
    private String address;  //地址

    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 getTel() {
        return tel;
    }

    public void setTel(String tel) {
        this.tel = tel;
    }

    public String getAddress() {
        return address;
    }

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

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", tel='" + tel + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

 

 

(2)在pojo包下新建User的扩展类UserExt,继承User,并把Card的属性添加进来,提供对应的getter、setter方法。

package com.chy.pojo;

public class UserExt extends User {
    private Integer no;
    private float money;

    public Integer getNo() {
        return no;
    }

    public void setNo(Integer no) {
        this.no = no;
    }

    public float getMoney() {
        return money;
    }

    public void setMoney(float money) {
        this.money = money;
    }

    @Override
    public String toString() {
        return super.toString()+",Card{" +
                "no=" + no +
                ", money=" + money +
                '}';
    }
}

先alt+insert插入toString(),再拼接上User的toString(),然后修改下就ok。

 

 

(3)编写UserMapper接口、UserMapper.xml

package com.chy.mapper;

import com.chy.pojo.UserExt;

public interface UserMapper {
    public UserExt queryUserExtById(Integer id);
}
<?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.chy.mapper.UserMapper">
    <select id="queryUserExtById" parameterType="integer" resultType="userext">
        SELECT user_tb.*,card_tb.* FROM user_tb,card_tb WHERE user_tb.id=#{id} AND user_tb.card_no=card_tb.no
     </select>
</mapper>

 

 

(4)使用

package com.chy.utils;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;

public class MyBatisUtils {
    private static SqlSessionFactory sqlSessionFactory;

    static {
        try {
            InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static SqlSession getSqlSession(){
        return sqlSessionFactory.openSession();
    }
}

 

SqlSession sqlSession = MyBatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        UserExt userExt = mapper.queryUserExtById(1);
        System.out.println(userExt);
        sqlSession.close();

 

使用扩展类可以实现一对一的关联查询,但没有体现实体之间的关联关系(一个模型中包含另一个模型)。

 

 

 


 

 

 

使用嵌套查询

(1)给2个“一”都编写pojo类,需要在一个“一”中关联另一个“一”

package com.chy.pojo;

public class User {
    private Integer id;  //主键
    private String name;  //姓名
    private String tel;  //手机号
    private String address;  //地址
    private Card 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 String getTel() {
        return tel;
    }

    public void setTel(String tel) {
        this.tel = tel;
    }

    public String getAddress() {
        return address;
    }

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

    public Card getCard() {
        return card;
    }

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

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", tel='" + tel + '\'' +
                ", address='" + address + '\'' +
                ", card=" + card +
                '}';
    }
}

 

package com.chy.pojo;

public class Card {
    private Integer no;  //会员卡编号
    private Float money;  //余额

    public Integer getNo() {
        return no;
    }

    public void setNo(Integer no) {
        this.no = no;
    }

    public Float getMoney() {
        return money;
    }

    public void setMoney(Float money) {
        this.money = money;
    }

    @Override
    public String toString() {
        return "Card{" +
                "no=" + no +
                ", money=" + money +
                '}';
    }
}

 外键是用来辅助sql操作的,并不是实体的属性,所以pojo类一般不包含外键字段。

 

 

(2)给这2个pojo类都编写Mapper接口、xml映射文件

public interface CardMapper {
    public Card queryCardByUserId(Integer no);
}
<?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.chy.mapper.CardMapper">
    <select id="queryCardByNo" parameterType="integer" resultType="card">
        SELECT * FROM card_tb WHERE no=#{no}
     </select>
</mapper>

 

 

package com.chy.mapper;

import com.chy.pojo.User;

public interface UserMapper {
    public User queryUserById(Integer id);
}
<?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.chy.mapper.UserMapper">
    <select id="queryUserById" parameterType="integer" resultMap="userResultWithCard">
        SELECT * FROM user_tb WHERE id=#{id}
     </select>
    <resultMap id="userResultWithCard" type="user">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="tel" column="tel"/>
        <result property="address" column="address"/>
        <association property="card" select="com.chy.mapper.CardMapper.queryCardByNo" column="card_no" javaType="card" /> 
   </resultMap>
</mapper>

sql语句都是查询当前pojo类对应的数据表,但主动嵌套的查询要使用resultMap来设置关联对象的映射,被嵌套的查询则不必设置。

  • property指定表示关联对象的成员变量名
  • select指定要嵌套的查询(namespace+id),执行当前查询时,会自动嵌套指定的<select>进行查询
  • column指定要把当前pojo类对应的数据表的哪一列作为参数传递给select嵌套的查询。
  • javaType指定嵌套的查询返回的数据类型

 

 

(3)使用

package com.chy.utils;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;

public class MyBatisUtils {
    private static SqlSessionFactory sqlSessionFactory;

    static {
        try {
            InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static SqlSession getSqlSession(){
        return sqlSessionFactory.openSession();
    }
}

 

package com.chy.test;

import com.chy.mapper.UserMapper;
import com.chy.pojo.User;
import com.chy.utils.MyBatisUtils;
import org.apache.ibatis.session.*;
import java.io.IOException;

public class Test {
    public static void main(String[] args) {
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = mapper.queryUserById(1);
        System.out.println(user);
        sqlSession.close();
    }
}

 

使用嵌套查询体现了实体之间的关联关系,但一条查询会触发另一个与之关联的查询,另一个查询如果有与之关联的查询,也会触发.....可能引发链式反应,降低查询效率和数据库的性能。

 

 


 

 

 

使用嵌套结果

使用方式与嵌套查询大体相同,不同的只有第二步:

(二)编写UserMapper接口、UserMapper.xml

package com.chy.mapper;

import com.chy.pojo.User;

public interface UserMapper {
    public User queryUserById(Integer id);
}

 

<?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.chy.mapper.UserMapper">
    <select id="queryUserById" parameterType="integer" resultMap="userResultWithCard">
        SELECT user_tb.*,card_tb.* FROM user_tb,card_tb WHERE user_tb.id=#{id} AND user_tb.card_no=card_tb.no
     </select>
    <resultMap id="userResultWithCard" type="user">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="tel" column="tel"/>
        <result property="address" column="address"/>
        <association property="card" javaType="card">
            <id property="no" column="no"/>
            <result property="money" column="money"/>
        </association>
    </resultMap>
</mapper>

因为只查询一次,所以要选取所有需要的数据。

<association>指定与之关联的实体的映射。

  • property表示关联对象的成员变量名
  • javaType指定返回的数据类型,mybatis根据javaType找到关联对象对应的pojo类。

嵌套结果只需指定2个属性,而嵌套查询要用select指定嵌套的<select>,还需要用column向嵌套的查询传递参数,所以嵌套查询需要指定4个属性。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!