day03-Mybatis中一对一、一对多、多对多查询
一对一查询
一对一的表结构:
my_account表:
my_user表:
一对一是互相的,A可以找到B,B也可以找到A,方法是一样的,这里就只写一个方向的
通过my_count表找到my_user表的对应元素
实际意义:一个账户(银行卡)只能被一个用户拥有
方法一(最常用):在Account实体类包含一个User类型对象的引用
Account实体类:
package com.zyb.pojo; import java.io.Serializable; import java.util.List; public class Account implements Serializable { private Integer id; private Integer uid; private Double money; //包含另一个对象的引用 private User user; public Account() { } @Override public String toString() { return "Account{" + "id=" + id + ", uid=" + uid + ", money=" + money + ", user=" + user + '}'; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Integer getUid() { return uid; } public void setUid(Integer uid) { this.uid = uid; } public Double getMoney() { return money; } public void setMoney(Double money) { this.money = money; } }
User实体类:
package com.zyb.pojo; import java.util.Date; import java.util.List; public class User { private int uid; private String uname; private Date birthday; private String userSex; private String userAddress; public User() { } public User(int uid, String uname, Date birthday, String userSex, String userAddress) { this.uid = uid; this.uname = uname; this.birthday = birthday; this.userSex = userSex; this.userAddress = userAddress; } @Override public String toString() { return "User{" + "uid=" + uid + ", uname='" + uname + '\'' + ", birthday=" + birthday + ", userSex='" + userSex + '\'' + ", userAddress='" + userAddress + '\'' + '}'; } public int getUid() { return uid; } public void setUid(int uid) { this.uid = uid; } public String getUname() { return uname; } public void setUname(String uname) { this.uname = uname; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public String getUserSex() { return userSex; } public void setUserSex(String userSex) { this.userSex = userSex; } public String getUserAddress() { return userAddress; } public void setUserAddress(String userAddress) { this.userAddress = userAddress; } }
AccountMapper.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.zyb.dao.AccountDao"> <resultMap id="accountUserMap" type="com.zyb.pojo.Account"> <!--这里写account_id是因为id重名在SQL语句中起的别名--> <id property="id" column="account_id"></id> <result property="uid" column="uid"></result> <result property="money" column="money"></result> <!-- 一对一关系映射配置user的--> <!-- 下面property是user是因为在Account实体类User类型变量名是user 第二个javaType是user是因为我给User实体类在mybatis-config.xml起了别名 --> <association property="user" javaType="user"> <!--主键字段对应--> <id property="uid" column="id"></id> <!-- 非主键属性对应--> <result property="uname" column="username"></result> <result property="birthday" column="birthday"></result> <result property="userSex" column="sex"></result> <result property="userAddress" column="address"></result> </association> </resultMap> <select id="selAllAccount" resultType="com.zyb.pojo.Account"> select * from my_account </select> <!-- 通过书写Account的子类完成一对多--> <!-- <select id="selAllAccount2User" resultType="com.zyb.pojo.AccountUser" >--> <!-- select a.*,u.username,u.address from my_account a,my_user u where a.uid=u.id;--> <!-- </select>--> <select id="selAllAccount2User" resultType="com.zyb.pojo.Account" resultMap="accountUserMap" > select u.*,a.id as account_id,a.money,a.uid from my_user u,my_account a where a.UID=u.id </select> </mapper>
测试类:
package com.zyb.test; import com.zyb.dao.AccountDao; import com.zyb.pojo.Account; import com.zyb.pojo.AccountUser; 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 org.junit.After; import org.junit.Before; import org.junit.Test; import java.io.IOException; import java.io.InputStream; import java.util.List; public class AccountTst { InputStream in; SqlSession session; AccountDao accountDao; @Before public void init() throws IOException { //1.读取配置文件 in = Resources.getResourceAsStream("mybatis-config.xml"); //2.创建SqlSessionFactory工厂 SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); SqlSessionFactory factory = builder.build(in); //3.使用工厂生产SqlSession对象 session = factory.openSession(); //4.使用SqlSession创建Dao接口的代理对象 accountDao = session.getMapper(AccountDao.class); } @After public void destory() throws IOException { //session.commit(); //6.释放资源 session.close(); in.close(); } @Test public void testSelAllAccount(){ List<Account> accounts = accountDao.selAllAccount(); accounts.forEach(x-> System.out.println(x)); } @Test public void testSelAllAccount2User(){ List<Account> accountUsers=accountDao.selAllAccount2User(); accountUsers.forEach(x-> System.out.println(x)); } }
方法二:建立一个中间类(属性包含需要查询User类的属性)继承Account之后,之后返回一个中间类型的列表就ok了
中间类:
package com.zyb.pojo; public class AccountUser extends Account{ private String username; private String address; public AccountUser() { } @Override public String toString() { return super.toString()+"AccountUser{" + "username='" + username + '\'' + ", address='" + address + '\'' + '}'; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }
AccountMapper.xml中的SQL语句以及配置就是上面注释的那个
测试文件将
换成
不细说这个了,不常用。
一对多查询
需要用到的表:my_user、my_account
实际意义:一个用户可以有多个账户(银行卡)
思路:通过上面的一对一,这个思路应该就不是很难想,那就是用户(User)包含一个属于自己账户集合的引用
user实体类:
与上面比就多了一个
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.zyb.dao.UserDao"> <!-- 返回类型可以写成user是因为我在mybatis-config.xml已经声明了,否则得写全限定类名--> <resultMap id="userMap" type="user"> <!--主键字段对应--> <id property="uid" column="id"></id> <!-- 非主键属性对应--> <result property="uname" column="username"></result> <result property="birthday" column="birthday"></result> <result property="userSex" column="sex"></result> <result property="userAddress" column="address"></result> <!-- 这里写accounts是因为在User中List<Account>的变量名为accounts--> <collection property="accounts" ofType="com.zyb.pojo.Account"> <!-- aid是列名重复SQl语句起别名的缘故--> <id property="id" column="aid"></id> <result property="uid" column="uid"></result> <result property="money" column="money"></result> </collection> </resultMap> <sql id="defaultSql"> select * from my_user </sql> <select id="selAll" resultType="User" resultMap="userMap"> select u.*,a.id as aid,a.uid,a.money from my_user u left outer join my_account a on a.uid=u.id <!--根据id查询一个人--> </select> <select id="selOne" resultType="USER" resultMap="userMap" parameterType="int"> <include refid="defaultSql"></include> where id=#{uid}; </select> </mapper>
测试类:
package com.zyb.test; import com.zyb.dao.UserDao; import com.zyb.pojo.User; 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 org.junit.After; import org.junit.Before; import org.junit.Test; import java.io.IOException; import java.io.InputStream; import java.util.List; public class TestUnit { InputStream in; SqlSession session; UserDao userDao; @Before public void init() throws IOException { //1.读取配置文件 in = Resources.getResourceAsStream("mybatis-config.xml"); //2.创建SqlSessionFactory工厂 SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); SqlSessionFactory factory = builder.build(in); //3.使用工厂生产SqlSession对象 session = factory.openSession(); //4.使用SqlSession创建Dao接口的代理对象 userDao = session.getMapper(UserDao.class); } @After public void destory() throws IOException { //session.commit(); //6.释放资源 session.close(); in.close(); } @Test public void testSelAll(){ List<User>users= userDao.selAll(); for(User user:users){ System.out.println("----------------------------------------"); System.out.println(user); System.out.println(user.getAccounts()); System.out.println("************************************************"); } } @Test public void testSelOne(){ User user = userDao.selOne(52); System.out.println(user); } }
测试结果:老王有两个账户,传智播客有一个,其它都是空
多对多查询
需要用到的表:my_user、my_role、role_user
思路:互相包含对方类型的的集合
实际意义:一个人扮演多个角色(儿子、父亲、学生),一个角色被多个人扮演
my_role:
user_role(中间表):
注意:这里的uid与my_user表的id相关联,rid与my_role的id相关联
Role实体类:
package com.zyb.pojo; import java.io.Serializable; import java.util.List; public class Role implements Serializable { private Integer roleId; private String roleName; private String roleDesc; private List<User> users; public Role() { } public List<User> getUsers() { return users; } public void setUsers(List<User> users) { this.users = users; } @Override public String toString() { return "Role{" + "roleId=" + roleId + ", roleName='" + roleName + '\'' + ", roleDesc='" + roleDesc + '\'' + '}'; } public Integer getRoleId() { return roleId; } public void setRoleId(Integer roleId) { this.roleId = roleId; } public String getRoleName() { return roleName; } public void setRoleName(String roleName) { this.roleName = roleName; } public String getRoleDesc() { return roleDesc; } public void setRoleDesc(String roleDesc) { this.roleDesc = roleDesc; } }
User实体类:
package com.zyb.pojo; import java.util.Date; import java.util.List; public class User { private int uid; private String uname; private Date birthday; private String userSex; private String userAddress; //一对多映射 //主表应该包含从表对象集合的引用 //之后collection的property属性填roles private List<Role> roles; public List<Role> getRoles() { return roles; } public void setRoles(List<Role> roles) { this.roles = roles; } public User() { } public User(int uid, String uname, Date birthday, String userSex, String userAddress) { this.uid = uid; this.uname = uname; this.birthday = birthday; this.userSex = userSex; this.userAddress = userAddress; } @Override public String toString() { return "User{" + "uid=" + uid + ", uname='" + uname + '\'' + ", birthday=" + birthday + ", userSex='" + userSex + '\'' + ", userAddress='" + userAddress + '\'' + '}'; } public int getUid() { return uid; } public void setUid(int uid) { this.uid = uid; } public String getUname() { return uname; } public void setUname(String uname) { this.uname = uname; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public String getUserSex() { return userSex; } public void setUserSex(String userSex) { this.userSex = userSex; } public String getUserAddress() { return userAddress; } public void setUserAddress(String userAddress) { this.userAddress = userAddress; } }
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.zyb.dao.UserDao"> <!-- 返回类型可以写成user是因为我在mybatis-config.xml已经声明了,否则得写全限定类名--> <resultMap id="userMap" type="user"> <!--主键字段对应--> <id property="uid" column="id"></id> <!-- 非主键属性对应--> <result property="uname" column="username"></result> <result property="birthday" column="birthday"></result> <result property="userSex" column="sex"></result> <result property="userAddress" column="address"></result> <collection property="roles" ofType="com.zyb.pojo.Role"> <id property="roleId" column="rid"></id> <result property="roleName" column="role_name"></result> <result property="roleDesc" column="role_desc"></result> </collection> </resultMap> <sql id="defaultSql"> select * from my_user </sql> <select id="selAll" resultMap="userMap"> select u.*,r.ROLE_NAME,r.ROLE_DESC,r.ID as rid from my_user u left outer join user_role ur on u.id=ur.UID left outer join my_role r on r.ID=ur.RID <!--根据id查询一个人--> </select> <select id="selOne" resultType="USER" resultMap="userMap" parameterType="int"> <include refid="defaultSql"></include> where id=#{uid}; </select> </mapper>
RoleMapper.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.zyb.dao.RoleDao"> <resultMap id="roleMap" type="com.zyb.pojo.Role"> <!-- 因为有两个id所以在查询结果重命名了id--> <!-- select u.*,r.ROLE_NAME,r.ROLE_DESC,r.ID as rid--> <id property="roleId" column="rid"></id> <result property="roleName" column="role_name"></result> <result property="roleDesc" column="role_desc"></result> <!-- collection中的property是包含集合的名字--> <collection property="users" ofType="user"> <!--主键字段对应--> <id property="uid" column="id"></id> <!-- 非主键属性对应--> <result property="uname" column="username"></result> <result property="birthday" column="birthday"></result> <result property="userSex" column="sex"></result> <result property="userAddress" column="address"></result> </collection> </resultMap> <select id="selAll" resultMap="roleMap"> select u.*,r.ROLE_NAME,r.ROLE_DESC,r.ID as rid from my_role r left outer join user_role ur on r.ID=ur.RID left outer join my_user u on ur.UID=u.id </select> </mapper>
测试类大同小异就不写了
运行结果:
}
不一样的烟火