MyBatis 关联关系的实现:一对一,
分享于 点击 42980 次 点评:133
MyBatis 关联关系的实现:一对一,
有2个实体:用户、会员卡,一个用户只能办理一张会员卡,即一对一。
user_tb : 引入card_tb的主键card_no作为外键。
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();
总结
- 使用扩展类实现一对一,主要靠映射文件中的sql语句,写的sql语句往往很复杂
- 因为要在“一”中添加另一个“一”的属性,如果另一个“一”的属性较多,添加起来就比较麻烦,即适合属性少的
- 没有体现实体之间的关联关系(一个pojo中包含另一个pojo)
方式二:使用嵌套查询实现一对一
(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; //与之关联的另一个“一” 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 + '}'; } }
(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" column="card_no" javaType="card" select="com.chy.mapper.CardMapper.queryCardByNo"/> </resultMap> </mapper>
sql语句都是查询当前pojo类对应的数据表,但UserMapper使用<resultMap>的<association>元素指定了嵌套查询。
- property属性指定当前pojo类中表示另一个“一”的属性名
- column属性指定当前数据表中关联另一个“一”的列(外键)
- javaType属性指定与当前pojo类关联的另一个“一”的数据类型。
- select属性指定要使用的另一个“一”的哪个sql元素关联(namespace+id),执行当前<select>查询时,会自动嵌套另一个“一”的<select>进行查询。
(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(); } }
总结:
使用嵌套查询体现了实体之间的关联关系,但一条查询会触发另一个与之关联的查询,另一个查询如果有与之关联的查询,也会触发.....链式反应,极大地降低了查询效率和数据库的性能,不推荐。
方式三:使用嵌套结果实现一对一
其他步骤与嵌套查询一样,不同的有2点:
(一)UserMapper.xml文件
<?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 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" javaType="card"> <id property="no" column="card_no"/> <result property="money" column="money"/> </association> </resultMap> </mapper>
sql语句变了,因为是一次查询,所以要查到所有需要的数据。
- property属性指定表示另一个“一”的属性名(成员变量名)
- javaType指定另一个“一”的数据类型
- <id>元素是关键,property指定另一个“一”的pojo类的哪个属性是主键,column指定哪个列与另一个“一”关联(外键)。
- <result>配置另一个“一”的映射
(二)因为不需要嵌套CardMapper的<select>进行查询,所以不需要CardMapper接口、CardMapper.xml。
总结
嵌套结果体现了实体之间的关联关系,且要写的代码更少,配置简单。推荐使用。
相关文章
- 暂无相关文章
用户点评