前置工作
创建一张account表和user表
user表:
account表:
外键uid对应user表中的id
插入数据:uid可以重复,表示一个用户可能有多个账户(卡)
一、查询所有的账户信息(及对应用户)
(1)创建账户表的持久接口
1、目录结构如下
2、接口代码如下
public interface IAccountDao {
/**
* 查找account账户信息以及所对应的用户信息的 姓名,地址
* @return
*/
List<Account> findAll();
}
(2)创建java实体类Account
目录结构如下
代码如下
值得注意的是这里创建一个User对象,用于返回对应的user的信息
其它即根据数据表中字段创建相同的java字段名,也生成get&set&tostring
public class Account implements Serializable {
private Integer id;
private Integer uid;
private Double money;
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.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;
}
@Override
public String toString() {
return "Account{" +
"id=" + id +
", uid=" + uid +
", money=" + money +
'}';
}
}
另:User类中代码(省去了相应的get&set)
(3)重点,编写xml文件
1、创建xml文件IAcountDao.xml
2、编写xml,代码如下
type对应的是account
实体类,数据要封装到这个实体类中
<id property="id" column="aid"></id>
,由于下面sql语句将a.id as aid
,所以这里account类中的id
需要对应的列名为aid
这里引入了<association>
标签,请看注释
<?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.itheima.dao.IAccountDao">
<resultMap id="accountUserMap" type="account">
<!--这一行的column为aid是因为,在下面查询语句,执行了 a.id as aid 的操作,所以这里对应的数据库字段应该为aid-->
<id property="id" column="aid"></id>
<result property="uid" column="uid"></result>
<result property="money" column="money"></result>
<!--这里property应该为与account相关联的表,column为account中与property处的表关联的数据库字段(外键),字段类型来自于java里面的user类 ,对应javaType-->
<association property="user" column="uid" javaType="user">
<id property="id" column="uid"></id>
<result property="username" column="username"></result>
<result property="birthday" column="birthday"></result>
<result property="sex" column="sex"></result>
<result property="address" column="address"></result>
</association>
</resultMap>
<select id="findAll" resultMap="accountUserMap">
select u.*,a.id as aid,a.uid,a.money from account a,user u where u.id=a.uid
</select>
</mapper>
其中,通过sql语句可以发现,这里用了a.id as aid
的取别名做法。
原因是,account表中有id,对应的账户的id(可以理解为卡号),user表中也有id,对应用户的id,通过观察表可以发现,其实account表中的id为大写的ID,为什么会冲突呢,因为mysql语句在windows系统下不区分大小写,所以视为这两个是一样的。如果不加这个,在查询的时候数据库会为我们自动创建一个列名为ID1的列对应account的id列。如下图。
新建查询:
可以看到上图,账户对应的id列名已经变成了id(1)
为了更好的控制列名,我们直接将a.id命名为aid。
(4)编写测试类
通过accountDao.findAll()来获取所有的账户放在Account类对象集合中
通过getUser来拿到对应的用户信息。
public class MybatisTest {
InputStream in;
private SqlSessionFactory factory;
SqlSession session;
IAccountDao accountDao;
@Before
public void init() throws IOException {
//1.获取配置文件流
in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂
factory = new SqlSessionFactoryBuilder().build(in);
//3.用工厂创建一个SqlSession
session = factory.openSession();
//4.用SqlSession创建一个Dao接口的代理
accountDao = session.getMapper(IAccountDao.class);
}
@After
public void destroy() throws IOException{
session.commit();
session.close();
in.close();
}
@Test
public void testFindAll(){
List<Account> accounts = accountDao.findAll();
for (Account account:accounts){
System.out.println("------one data-------");
System.out.println(account);
System.out.println(account.getUser());
}
}
}
运行一下测试类:
可以看到,account表中的数据全有了,并且也打印出了每个账户所对应的用户信息。
二、查询用户信息并打印该用户的所有账户
(1)在IUserDao接口中添加方法
findAllUserAndAccounts(); 返回一个用户列表
(2)对User实体类做相应改造
为每个用户添加一个Account列表,用于储存该用户所有账户,并生成get&set
(3)编写xml文件
值得注意的为:(详细看注释)
此处的<collection>
标签的各个属性
以及sql语句采用左表外连接
<?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.itheima.dao.IUserDao">
<resultMap id="userAndAccountMap" type="user">
<id property="id" column="id"></id>
<result property="username" column="username"></result>
<result property="birthday" column="birthday"></result>
<result property="sex" column="sex"></result>
<result property="address" column="address"></result>
<!--配置user对象中的accounts集合的映射-->
<!--一个集合标签,property为集合名,ofType表示集合里面是什么类型的对象,没起别名的时候ofType应该为全限定类名-->
<collection property="accounts" ofType="account">
<id property="id" column="aid"></id>
<result property="uid" column="uid"></result>
<result property="money" column="money"></result>
</collection>
</resultMap>
<select id="findAllUserAndAccounts" resultMap="userAndAccountMap">
<!--采用左表外连接 显示所有user的同时也显示他们的accounts-->
select *,a.id as aid from user u left outer join account a on u.id=a.uid
</select>
</mapper>
(4)编写test类
因为上一个例子用了把原来的MybatisTest中的代理改成account的代理了,这里方便起见重新创建一个类
public class TestUserAndAccount {
InputStream in;
private SqlSessionFactory factory;
SqlSession session;
IUserDao userDao;
@Before
public void init() throws IOException {
//1.获取配置文件流
in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂
factory = new SqlSessionFactoryBuilder().build(in);
//3.用工厂创建一个SqlSession
session = factory.openSession();
//4.用SqlSession创建一个Dao接口的代理
userDao = session.getMapper(IUserDao.class);
}
@After
public void destroy() throws IOException{
session.commit();
session.close();
in.close();
}
@Test
public void testFindAll(){
List<User> users = userDao.findAllUserAndAccounts();
for (User user:users) {
//只获取有账户信息的用户,并打印其所有账户信息
if (user.getAccounts().size() > 0) {
System.out.println("-------one data---------");
System.out.println(user);
System.out.println(user.getAccounts());
}
}
}
}
运行结果:
妹毛病嗷铁汁!
前置工作(二)
(1)新建一张表role,存放角色信息
(2)创建一张中间表uer_role来存放user和role的关系的关系,其中rid对应角色的id,uid对应user的id
一、查询一个用户对应的所有角色
(1)新建IUserDao接口类
public interface IUserDao {
List<User> findAll();
}
(2)新建Role实体类并在User类里添加相应内容
编写与数据库内容对应的字段名,并且生成相应的set&get&toString
(这里字段和数据库的字段不统一,所以在下面编写xml的时候要写一个resultMap映射)
在User类中添加Role集合,并生成相应的set&get
private List<Role> roles;
(3)编写IUserDao.xml文件
详细的sql语句的解释在下列代码中
<?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.itheima.dao.IUserDao">
<!--编写对应的结果映射,映射字段到user实体类中-->
<resultMap id="userRoleMap" type="user">
<id property="id" column="id"></id>
<result property="username" column="username"></result>
<result property="birthday" column="birthday"></result>
<result property="sex" column="sex"></result>
<result property="address" column="address"></result>
<!--对User类中的Role集合实体类进行映射,property为集合类型,ofType为对应的实体类名-->
<collection property="roles" ofType="role" >
<id property="roleId" column="role_id"></id>
<result property="roleName" column="role_name"></result>
<result property="roleDesc" column="role_desc"></result>
</collection>
</resultMap>
<select id="findAll" resultMap="userRoleMap">
<!--采用左表外连接,
先用user表 左表外连接中间表(当user的id == user_role表中的uid)
再用上面已经取得的结果表
结果表 左表外连接角色表(当role的id == 中间表对应的rid )
由此两个表都对应起来,拿到了user对应的角色信息
-->
select u.*,r.* from user u
left outer join user_role ur on u.id = ur.uid
left outer join role r on r.role_id = ur.rid
</select>
</mapper>
(4)编写测试类
package com.itheima.test;
import com.itheima.dao.IUserDao;
import com.itheima.domain.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 UserRoleTest {
private InputStream in;
private SqlSessionFactory factory;
private SqlSession session;
IUserDao userDao;
@Before
public void init() throws IOException {
in = Resources.getResourceAsStream("SqlMapConfig.xml");
factory = new SqlSessionFactoryBuilder().build(in);
session = factory.openSession();
userDao = session.getMapper(IUserDao.class);
}
@After
public void destroy () throws IOException {
session.commit();
in.close();
}
@Test
public void testUserRoles(){
List<User> users = userDao.findAll();
for (User user:users){
//为了方便显示,这里只打印有角色信息的用户
if (user.getRoles().size() > 0){
System.out.println("-------one data------");
System.out.println(user);
System.out.println(user.getRoles());
}
}
}
}
运行结果:
可以看到,id为75和id为76,角色均是副校长,而且id为75同时还是数学老师
二、查询一个角色对应的所有用户信息
(1)新建IRoleDao接口类
public interface IRoleDao {
List<Role> findAll();
}
(2)Role实体类新增字段
添加一个User集合,用来存放该角色下的所有用户信息
(3)新建xml文件
xml文件与上文类似
sql语句与上面只是反了一下,原理是一样的,不再赘述
<?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.itheima.dao.IRoleDao">
<resultMap id="roleMap" type="role">
<id property="roleId" column="role_id"></id>
<result property="roleName" column="role_name"></result>
<result property="roleDesc" column="role_desc"></result>
<collection property="users" ofType="user">
<id property="id" column="id"></id>
<result property="username" column="username"></result>
<result property="birthday" column="birthday"></result>
<result property="sex" column="sex"></result>
<result property="address" column="address"></result>
</collection>
</resultMap>
<select id="findAll" resultMap="roleMap">
select * from role r
left outer join user_role ur on ur.rid = r.role_id
left outer join user u on u.id = ur.uid
</select>
</mapper>
(4)编写测试类
新建测试类
package com.itheima.test;
import com.itheima.dao.IRoleDao;
import com.itheima.domain.Role;
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 RoleUserTest {
private InputStream in;
private SqlSessionFactory factory;
private SqlSession session;
IRoleDao roleDao;
@Before
public void init() throws IOException {
in = Resources.getResourceAsStream("SqlMapConfig.xml");
factory = new SqlSessionFactoryBuilder().build(in);
session = factory.openSession();
roleDao = session.getMapper(IRoleDao.class);
}
@After
public void destroy () throws IOException {
session.commit();
in.close();
}
@Test
public void testUserRoles(){
List<Role> roles = roleDao.findAll();
for (Role role:roles){
if (role.getUsers().size() > 0){
System.out.println("-------one data------");
System.out.println(role);
System.out.println(role.getUsers());
}
}
}
}
运行结果:
可以看到,也表明了有两个副校长。分别为id为75和76的用户
与上一块内容的结果对应起来了。
关于mybatis的多表查询相关入门到此告一段落。