MyBatis之多表之间的联系与缓存

来源:互联网 发布:lol免费充点卷软件. 编辑:程序博客网 时间:2024/06/02 03:19

多表之间的联系:

注:本文章的演示都是在上篇文章项目的基础上进行的,所以有的代码变动不大的就不再重复贴了,以免太过冗余。点明一点:每写一个映射文件都要配置在mybatis-config.xml 的 <mappers>中

一对多:查询哪些人有哪些车

Demo3.java

[java] view plain copy
 print?
  1. package cn.hncu.demo;  
  2.   
  3. import java.sql.SQLException;  
  4. import java.util.List;  
  5. import java.util.Set;  
  6.   
  7. import org.apache.ibatis.session.SqlSession;  
  8. import org.junit.Test;  
  9.   
  10. import cn.hncu.domain.Card;  
  11. import cn.hncu.domain.Person;  
  12. import cn.hncu.domain.Role;  
  13. import cn.hncu.domain.User;  
  14. import cn.hncu.utils.SqlSessionUtils;  
  15.   
  16. //演示表与表之间的关系:一对一,一对多和多对多  
  17. public class Demo3 {  
  18.       
  19.     //一对多:一个人(person)多辆车(car)  
  20.     @Test  
  21.     public void test1() throws SQLException{  
  22.         //查询哪些人有哪些车-----innor join  
  23.         SqlSession s=SqlSessionUtils.getSqlSession();  
  24.         List<Person> persons=s.selectList("persons.person1");  
  25.         s.close();  
  26.         for(Person person:persons)  
  27.         System.out.println("person: "+person);  
  28.     }  


Person.java

[java] view plain copy
 print?
  1. package cn.hncu.domain;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.List;  
  5.   
  6. //一方  
  7. public class Person {  
  8.     private String id;  
  9.     private String name;  
  10.       
  11.     //建一个集合表示多方  
  12.     private List<Car> cars=new ArrayList<Car>();  
  13.       
  14.     //为了实现表之间关系中的“一对一”,在此必须添加一个对方的值对象  
  15.     private Card card;  
  16.     public String getId() {  
  17.         return id;  
  18.     }  
  19.     public void setId(String id) {  
  20.         this.id = id;  
  21.     }  
  22.     public String getName() {  
  23.         return name;  
  24.     }  
  25.     public void setName(String name) {  
  26.         this.name = name;  
  27.     }  
  28.     public List<Car> getCars() {  
  29.         return cars;  
  30.     }  
  31.     public void setCars(List<Car> cars) {  
  32.         this.cars = cars;  
  33.     }  
  34.       
  35.     public Card getCard() {  
  36.         return card;  
  37.     }  
  38.     public void setCard(Card card) {  
  39.         this.card = card;  
  40.     }  
  41.     @Override  
  42.     public String toString() {  
  43.         return "Person [id=" + id + ", name=" + name + ", cars=" + cars + "]";  
  44.     }  
  45.       
  46. }  


Car.java

[java] view plain copy
 print?
  1. package cn.hncu.domain;  
  2.   
  3. //多方  
  4. public class Car {  
  5.     private String id;  
  6.     private String name;  
  7.     private Double price;  
  8.       
  9.     //声明一个值对象表示一方  
  10.     private Person person;  
  11.       
  12.     public String getId() {  
  13.         return id;  
  14.     }  
  15.     public void setId(String id) {  
  16.         this.id = id;  
  17.     }  
  18.     public String getName() {  
  19.         return name;  
  20.     }  
  21.     public void setName(String name) {  
  22.         this.name = name;  
  23.     }  
  24.     public Double getPrice() {  
  25.         return price;  
  26.     }  
  27.     public void setPrice(Double price) {  
  28.         this.price = price;  
  29.     }  
  30.     public Person getPerson() {  
  31.         return person;  
  32.     }  
  33.     public void setPerson(Person person) {  
  34.         this.person = person;  
  35.     }  
  36.     @Override  
  37.     public String toString() {  
  38.         return "Car [id=" + id + ", name=" + name + ", price=" + price + "]";  
  39.     }  
  40.       
  41. }  


Person.xml

[html] view plain copy
 print?
  1. <?xml version="1.0" encoding="UTF-8" ?>  
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"  
  3. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">  
  4.   
  5. <!-- 该映射文件专用于演示表与表之间的关系 -->  
  6. <mapper namespace="persons">  
  7.       
  8.     <!-- 一对多:inner join-->  
  9.     <!-- 自定义复杂类型用resultMap -->  
  10.     <resultMap type="cn.hncu.domain.Person" id="ps">  
  11.         <id property="id" column="pid"/><!-- 使用id是为了更加精确,使用result也可 -->  
  12.         <result property="name" column="pname"/>  
  13.           
  14.         <!-- 一方中的多方集合(这里的property用car值对象的变量,column用下面select语句的查询结果的表头) -->  
  15.         <collection property="cars" javaType="cn.hncu.domain.Car">  
  16.             <id property="id" column="cid"/>  
  17.             <result property="name" column="cname" javaType="string" jdbcType="VARCHAR"/>  
  18.             <result property="price" column="cprice" javaType="_double" jdbcType="NUMERIC"/>  
  19.         </collection>  
  20.           
  21.     </resultMap>  
  22.     <select id="person1" resultMap="ps">  
  23.         select p.pid as pid,p.pname as pname,c.id as cid,c.name as cname,c.price as cprice  
  24.         from person p inner join car c on p.pid =c.pid  
  25.     </select>  


数据库查询结果:

 

控制台查询结果:

 

一对多:查询每个人的车辆信息-----left join

[java] view plain copy
 print?
  1. @Test  
  2.     public void test2() throws SQLException{  
  3.         //查询每个人的车辆信息-----left join  
  4.         SqlSession s=SqlSessionUtils.getSqlSession();  
  5.         List<Person> persons=s.selectList("persons.person2");  
  6.         s.close();  
  7.         for(Person person:persons)  
  8.             System.out.println("person: "+person);  
  9.     }  


 

[html] view plain copy
 print?
  1. <!-- 一对多:按照上面的方法用left join即可,这里学习一下嵌套查询 -->  
  2.     <select id="person2" resultMap="ps2">  
  3.         select pid,pname from person  
  4.     </select>  
  5.     <resultMap type="cn.hncu.domain.Person" id="ps2">  
  6.         <id property="id" column="pid"/>  
  7.         <result property="name" column="pname"/>  
  8.         <collection property="cars" column="pid" select="cars1"></collection>  
  9.     </resultMap>  
  10.     <select id="cars1" resultType="cn.hncu.domain.Car" parameterType="string">  
  11.         select * from car where pid=#{value}  
  12.     </select>  


数据库:

控制台:

 

一对一:一个人对应一张身份证

[java] view plain copy
 print?
  1. @Test  
  2.     public void test3() throws SQLException{  
  3.         //查询每个人的车辆信息-----left join  
  4.         SqlSession s=SqlSessionUtils.getSqlSession();  
  5.         List<Card> cards=s.selectList("persons.card1");  
  6.         s.close();  
  7.         for(Card card:cards)  
  8.             System.out.println("card: "+card);  
  9.     }  


 

[html] view plain copy
 print?
  1. <!-- 一对一演示:一张身份证对应一个人 -->  
  2.     <select id="card1" resultMap="c1">  
  3.         select c.card_id as id,c.card_gov as gov,p.pid as pid,p.pname as pname  
  4.         from cards c inner join person p on c.pid=p.pid  
  5.     </select>  
  6.     <resultMap type="cn.hncu.domain.Card" id="c1">  
  7.         <!-- 以指定构造方法来初始化对象 -->  
  8.         <constructor>  
  9.             <idArg column="id" javaType="string" jdbcType="VARCHAR"/>  
  10.         </constructor>  
  11.         <result property="gov" column="gov" javaType="string" jdbcType="VARCHAR"/>  
  12.         <association property="person"  javaType="cn.hncu.domain.Person">  
  13.             <result property="id" column="pid"/>  
  14.             <result property="name" column="pname"/>  
  15.             <collection property="cars" select="cars1" column="pid"></collection>  
  16.         </association>  
  17.     </resultMap>  
  18. </mapper>  


数据库:

 

控制台:

 

多对多:人---角色的关系

[java] view plain copy
 print?
  1. //多对多:人---角色的关系    开发步骤:1.建数据库表  2.写值对象(体现表之间关系)  3.写调用的java代码(在业务流程不熟悉的情况下,可先从需求下手) 4.写映射文件  
  2.     @Test  
  3.     public void test4() throws SQLException{  
  4.         //查询哪些人有哪些角色-----inner join  
  5.         SqlSession s=SqlSessionUtils.getSqlSession();  
  6.         List<User> users=s.selectList("roles.user");  
  7.         s.close();  
  8.         for(User user:users)  
  9.             System.out.println("user: "+user);  
  10.         for(User u:users){  
  11.             String name=u.getName();  
  12.             Set<Role> roles=u.getRoles();  
  13.             String r="";  
  14.             for(Role role:roles){  
  15.                 r+=role.getName()+",";  
  16.             }  
  17.             System.out.println(name+","+r);  
  18.         }  
  19.     }  


Role.xml

[html] view plain copy
 print?
  1. <?xml version="1.0" encoding="UTF-8" ?>  
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"  
  3. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">  
  4. <mapper namespace="roles">  
  5.     <!-- 如果当前映射文件中的所有操作都要使用(二级)缓存,只需加<cache/>标记即可 -->  
  6.     <cache/>  
  7.       
  8.     <!-- 多对多:采用 inner join -->  
  9.     <select id="user" resultMap="us">  
  10.     select u.id as id , u.name as name , u.pwd as pwd , r.id as rid , r.name as rname  
  11.         from users u inner join userrole ur on u.id=ur.uid inner join roles r on ur.rid=r.id  
  12.     </select>  
  13.     <resultMap type="cn.hncu.domain.User" id="us">  
  14.     <id property="id" column="id"/>  
  15.     <result property="name" column="name" javaType="string" jdbcType="VARCHAR"/>  
  16.     <result property="pwd" column="pwd"/>  
  17.     <collection property="roles" javaType="cn.hncu.domain.Role">  
  18.         <id property="id" column="rid"/>  
  19.         <result property="name" column="rname"/>  
  20.     </collection>  
  21.     </resultMap>  

 

两个值对象:


User.java

[java] view plain copy
 print?
  1. package cn.hncu.domain;  
  2.   
  3. import java.util.HashSet;  
  4. import java.util.Set;  
  5.   
  6. public class User {  
  7.     private String id;  
  8.     private String name;  
  9.     private String pwd;  
  10.       
  11.     //专为多对多建立一个  保存对方的集合--用List或Set都可以  
  12.     private Set<Role> roles=new HashSet<Role>();  
  13.     public String getId() {  
  14.         return id;  
  15.     }  
  16.     public void setId(String id) {  
  17.         this.id = id;  
  18.     }  
  19.     public String getName() {  
  20.         return name;  
  21.     }  
  22.     public void setName(String name) {  
  23.         this.name = name;  
  24.     }  
  25.     public String getPwd() {  
  26.         return pwd;  
  27.     }  
  28.     public void setPwd(String pwd) {  
  29.         this.pwd = pwd;  
  30.     }  
  31.       
  32.     public Set<Role> getRoles() {  
  33.         return roles;  
  34.     }  
  35.     public void setRoles(Set<Role> roles) {  
  36.         this.roles = roles;  
  37.     }  
  38.     @Override  
  39.     public String toString() {  
  40.         return "User [id=" + id + ", name=" + name + ", pwd=" + pwd  
  41.                 + ", roles=" + roles + "]";  
  42.     }  
  43.       
  44. }  


Role.java

[java] view plain copy
 print?
  1. package cn.hncu.domain;  
  2.   
  3. import java.io.Serializable;  
  4. import java.util.ArrayList;  
  5. import java.util.List;  
  6.   
  7. public class Role implements Serializable{  
  8.     private String id;  
  9.     private String name;  
  10.       
  11.     //专为多对多建立一个保存对方的集合 -----用list或set 都可以  
  12.     private List<User> users=new ArrayList<User>();  
  13.   
  14.     public String getId() {  
  15.         return id;  
  16.     }  
  17.   
  18.     public void setId(String id) {  
  19.         this.id = id;  
  20.     }  
  21.   
  22.     public String getName() {  
  23.         return name;  
  24.     }  
  25.   
  26.     public void setName(String name) {  
  27.         this.name = name;  
  28.     }  
  29.   
  30.     public List<User> getUsers() {  
  31.         return users;  
  32.     }  
  33.   
  34.     public void setUsers(List<User> users) {  
  35.         this.users = users;  
  36.     }  
  37.   
  38.     @Override  
  39.     public String toString() {  
  40.         return "Role [id=" + id + ", name=" + name + "]";  
  41.     }  
  42.       
  43. }  


数据库:

 

控制台:

 

mybatis缓存技术演示

[java] view plain copy
 print?
  1. //※※mybatis缓存技术演示:  
  2.     //※※注意:被放入缓存的值对象必须实现serizable接口  
  3.     @Test  
  4.     public void caseDemo() throws SQLException{  
  5.           
  6.         //同一个session用的是一级缓存  
  7.         SqlSession ss=SqlSessionUtils.getSqlSession();  
  8.         System.out.println("ss: "+ss);  
  9.         Role role=ss.selectOne("roles.cacheDemo","R001");//查单  
  10.         System.out.println(role.hashCode());  
  11.         Role role2=ss.selectOne("roles.cacheDemo","R001");//查单  
  12.         System.out.println(role2.hashCode());  
  13.         ss.close();  
  14.           
  15.         System.out.println("----------------------------");  
  16.         //第二个session  
  17.         SqlSession ss2=SqlSessionUtils.getSqlSession();  
  18.         System.out.println("ss2: "+ss2);  
  19.         Role role22=ss2.selectOne("roles.cacheDemo","R001");//查单  
  20.         System.out.println(role22.hashCode());  
  21.         Role role222=ss2.selectOne("roles.cacheDemo","R001");//查单  
  22.         System.out.println(role222.hashCode());  
  23.           
  24.     }  
  25. }  

[html] view plain copy
 print?
  1. <!-- 下面的查询操作专用于演示缓存   useCache可指定某条语句不使用缓存-->  
  2.     <select id="cacheDemo" useCache="false" resultType="cn.hncu.domain.Role" parameterType="string">  
  3.         select * from roles where id=#{value}  
  4.     </select>  
  5. </mapper>  


不带缓存:

 

带缓存:

 

这里对缓存再个人总结一下:

 1.  缓存有一级和二级缓存。SqlSession自己带有一级缓存,所有同一个缓存得到的对象的hash地址是相同的,不同的session拿到的对象hash地址不同。

 2.  mybatis(hibernate也一样)有二级缓存。mytbatis中默认情况下是没有开启缓存的,当不同session查询时,都要去数据库中去查询,效率降低。

   当开启mybatis缓存时,session第一次查询时没有缓存,会到数据库中查询,并将查询结果放到mybatis二级缓存和本session缓存中,当再存查询时,会到本session缓存池中寻找,找到即返回结果。

    所以带缓存的图中,两次的hashCode值是一样的。    而当第二个session去查询时,到mybatis的二级缓存池中找到结果,就会把结果克隆一份结果返回,并且不把结果放进本session缓存池中,再次查询时,依然到mybatis的二级缓存池中中克隆结果。所以两次结果的hashCode值不同。

 3.  只有session到数据库中查询,才会把查询结果放进session的缓存池中。

 

贴出一下我用mysql建的表格的代码,以供日后参考:

[sql] view plain copy
 print?
  1. ALTER TABLE car   
  2.     ADD CONSTRAINT stud_fk FOREIGN KEY(pid) REFERENCES person(pid);  
  3. INSERT INTO person(pid,pname) VALUES("P001","Jack");  
  4. INSERT INTO person(pid,pname) VALUES("P002","Rose");  
  5. INSERT INTO person(pid,pname) VALUES("P003","Tom");  
  6. INSERT INTO car(id,NAME,price,pid) VALUES("C001","Benz",100,"P001");  
  7. INSERT INTO car(id,NAME,price,pid) VALUES("C002","BMW",150,"P001");  
  8. INSERT INTO car(id,NAME,price,pid) VALUES("C003","QQ",10,"P003");  
  9. DROP TABLE person;  
  10. DROP TABLE car;  
  11. CREATE TABLE car(  
  12. id VARCHAR(32) PRIMARY KEY,  
  13. NAME VARCHAR(128),  
  14. price NUMERIC,  
  15. pid VARCHAR(32)  
  16. );  
  17. SELECT pid,pname FROM person  
  18.   
  19.   
  20. SELECT p.pid AS pid,p.pname AS pname,c.id AS cid,c.name AS cname,c.price AS cprice  
  21.         FROM person p INNER JOIN car c ON p.pid =c.pid  
  22.           
  23. SELECT p.pid AS pid,p.pname AS pname,c.id AS cid,c.name AS cname,c.price AS cprice  
  24.         FROM person p LEFT JOIN car c ON p.pid =c.pid  
  25.   
  26.   
  27. CREATE TABLE cards(  
  28. card_id VARCHAR(32) PRIMARY KEY,  
  29. card_gov VARCHAR(128),  
  30. pid VARCHAR(32)  
  31. )  
  32. ALTER TABLE cards   
  33.     ADD CONSTRAINT fk_pid FOREIGN KEY (pid) REFERENCES person(pid);  
  34.   
  35. INSERT INTO cards(card_id,card_gov,pid) VALUES("C001","湖南长沙","P001");  
  36. INSERT INTO cards(card_id,card_gov,pid) VALUES("C002","湖南益阳","P002");  
  37. INSERT INTO cards(card_id,card_gov,pid) VALUES("C003","北京朝阳","P003");  
  38.   
  39. SELECT c.card_id AS id,c.card_gov AS gov,p.pid AS pid,p.pname AS pname  
  40.         FROM cards c INNER JOIN person p ON c.pid=p.pid  
  41.   
  42. CREATE TABLE roles(  
  43. id VARCHAR(32) PRIMARY KEY,  
  44. NAME VARCHAR(128)  
  45. )  
  46. INSERT INTO roles(id,NAMEVALUES('R001','教师');  
  47. INSERT INTO roles(id,NAMEVALUES('R002','学生');  
  48. INSERT INTO roles(id,NAMEVALUES('R003','后勤');  
  49. INSERT INTO roles(id,NAMEVALUES('R004','暂无');  
  50. CREATE TABLE userRole(  
  51. uid VARCHAR(32),  
  52. rid VARCHAR(32)  
  53. )  
  54. ALTER TABLE userrole   
  55.     ADD CONSTRAINT fk_uid FOREIGN KEY (uid) REFERENCES users(id);  
  56. ALTER TABLE userrole   
  57.     ADD CONSTRAINT fk_rid FOREIGN KEY (rid) REFERENCES roles(id);  
  58.   
  59. INSERT INTO userrole(uid,rid) VALUES('1',"R002");  
  60. INSERT INTO userrole(uid,rid) VALUES('1',"R003");  
  61. INSERT INTO userrole(uid,rid) VALUES('2',"R002");  
  62. INSERT INTO userrole(uid,rid) VALUES('3',"R004");  
  63. INSERT INTO userrole(uid,rid) VALUES('4',"R001");  
  64.   
  65. SELECT u.id AS id , u.name AS NAME , u.pwd AS pwd , r.id AS rid , r.name AS rname  
  66. FROM users u INNER JOIN userrole ur ON u.id=ur.uid INNER JOIN roles r ON ur.rid=r.id