有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個屬性。