有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个属性。
来源:oschina
链接:https://my.oschina.net/u/4395893/blog/3318482