表的关联关系
- 我们知道的关联关系一般有如下:
- 一对一、一对多、多对多
- 那么我们如果不用VO类,又如何通过Mybatis实现呢?
实现原理
- Mybatis是采用和表和类进行对应,所以我们联名表的关联,肯定也就是需要我们对象之间存在关系
- 这样理解就很简单了,例如:一个学生有无数门成绩,但是只有一个班级
- 那么我们学生类创建一个“成绩”的集合,然后创建一个“班级”的对象,然后我们分别对应赋值,这样不就是实现了关联了吗?
- 是不是很简单,那么具体实现请看下面源码展示
表以及公共类代码如下:
User
public class User {
private String id;
private String username;
private String password;
private Banji banji;
private List<Garde> gardeList;
public Banji getBanji() {
return banji;
}
public void setBanji(Banji banji) {
this.banji = banji;
}
public List<Garde> getGardeList() {
return gardeList;
}
public void setGardeList(List<Garde> gardeList) {
this.gardeList = gardeList;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public User(String id, String username, String password) {
super();
this.id = id;
this.username = username;
this.password = password;
}
public User() {
super();
}
@Override
public String toString() {
return "User [id=" + id + ", username=" + username + ", password=" + password + ", banji=" + banji
+ ", gardeList=" + gardeList + "]";
}
}
Banji
public class Banji {
private String username;
private String banji;
private String uid;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getBanji() {
return banji;
}
public void setBanji(String banji) {
this.banji = banji;
}
public String getUid() {
return uid;
}
public void setUid(String uid) {
this.uid = uid;
}
public Banji(String username, String banji,String uid) {
super();
this.username = username;
this.banji = banji;
this.uid = uid;
}
public Banji() {
super();
}
@Override
public String toString() {
return "Banji [username=" + username + ", banji=" + banji + ", uid=" + uid + "]";
}
}
Garde
public class Garde {
private String username;
private int garde;
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public int getGarde() {
return garde;
}
public void setGarde(int garde) {
this.garde = garde;
}
public Garde(String username, Integer garde, String id) {
super();
this.username = username;
this.garde = garde;
this.id = id;
}
public Garde(String username, int garde) {
super();
this.username = username;
this.garde = garde;
}
public Garde() {
super();
}
@Override
public String toString() {
return "Garde [username=" + username + ", garde=" + garde + ", id=" + id + "]";
}
}
JoinUserDao
public interface JoinUserDao {
public User findById(int id);
public List<User> findByUsername(int id);
public List<User> findByIdAll(int id);
}
一对一实现:
Mapper
<resultMap type="domain.User" id="UserMap">
<id column="id" property="id"/>
<result column="password" property="password"/>
<result column="username" property="username"/>
<association property="banji" javaType="domain.Banji">
<id column="id" property="uid"/>
<result column="username" property="username"/>
<result column="banji" property="banji"/>
</association>
</resultMap>
<select id="findById" parameterType="int" resultMap="UserMap">
select * from tb_user u,tb_banji b where u.id=b.uid and u.username=b.username and u.id=#{id}
</select>
测试文件
public class Text05 {
public static void main(String[] args) {
String resource="MybatisMainCof.xml";
InputStream is=Text01.class.getClassLoader().getResourceAsStream(resource);
SqlSessionFactory sessionFactory=new SqlSessionFactoryBuilder().build(is); //通过配置文件获取链接工厂
SqlSession sqlSession=sessionFactory.openSession(); //获取链接
JoinUserDao joinUserDao=sqlSession.getMapper(JoinUserDao.class);
User user=joinUserDao.findById(2);
System.out.println(user);
}
}
小结:
- 一对一实现还是很简单的,通过在map中使用关键字(association)
- resultMap标签的作用主要有以下两点
- 配置基础属性(也就是User的属性)
- 配置附加类(也就是Banji)
- 其中的配置方法和前面博客介绍的都是一样的,通过result标检配置
一对多实现方法(1):
Mapper
<resultMap type="domain.User" id="UserList">
<id column="id" property="id"/>
<result column="password" property="password"/>
<result column="username" property="username"/>
<collection property="gardeList" ofType="domain.Garde">
<result column="garde" property="garde"/>
<result column="username" property="username"/>
</collection>
</resultMap>
<select id="findByUsername" parameterType="int" resultMap="UserList">
select * from tb_user u,tb_garde g where u.username=g.username and u.id=#{id}
</select>
测试
public class Text05 {
public static void main(String[] args) {
String resource="MybatisMainCof.xml";
InputStream is=Text01.class.getClassLoader().getResourceAsStream(resource);
SqlSessionFactory sessionFactory=new SqlSessionFactoryBuilder().build(is); //通过配置文件获取链接工厂
SqlSession sqlSession=sessionFactory.openSession(); //获取链接
JoinUserDao joinUserDao=sqlSession.getMapper(JoinUserDao.class);
List<User> list=joinUserDao.findByUsername(2);
System.out.println(list);
}
}
小结:
- 这里的思路和一对一的思路都是一样的,仅仅是关键字不一样了
- 一对多,因为是有List,所以标签使用的是(collection),然后对应的类型是用的(ofType)
一对多的其余实现方法(2):
Mapper
<resultMap type="domain.User" id="UserList">
<id column="id" property="id"/>
<collection property="gardeList" ofType="domain.Garde" select="findByname" javaType="ArrayList" column="id" ></collection>
</resultMap>
<select id="findByname" parameterType="int" resultType="domain.Garde">
select * from tb_garde where id=#{id}
</select>
<select id="findByUsername" parameterType="int" resultMap="UserList">
select * from tb_user where id=#{id}
</select>
- 这个实现的思路有一点绕,首先通过findByUsername,查找,然后将返回的值返回给Map
- 然后进入resultMap,这里我们注意collection里面有个select属性,以及column属性
- 然后我们select属性就是对应的第二个查询了,也就是根据我们findByUsername获取出来的ID,查询出相应的成绩,然后保存
- 这个方法也可以用于一对一查询,都是通用的
- 下面通过一张图解释顺序
一对多的实现方法(3):
Mapper
<resultMap type="domain.User" id="UserList">
<id column="id" property="id"/>
<result column="password" property="password"/>
<result column="username" property="username"/>
<collection property="gardeList" ofType="domain.Garde">
<constructor>
<arg column="username" javaType="String"/>
<arg column="garde" javaType="int"/>
<arg column="id" javaType="String"/>
</constructor>
</collection>
</resultMap>
<select id="findByUsername" parameterType="int" resultMap="UserList">
select * from tb_user u,tb_garde g where u.username=g.username and u.id=#{id}
</select>
- 这个实现就比较简单了,就是通过构造器实现,和第一种方法差别不大,看个人兴趣
- 这里有个主意事项
- 那就是构造器了,因为构造器的顺序是和我们的构造函数一样,所以我们注意下顺序,别因为顺序出错而赋值出错
- 其次就是关于int类型的构造函数中要使用Integer,不然会报错
部分小结
- 我们以上实现的查询,都是实现的单一赋值
- 也就是要么实现一对一,要么实现一对多,并没有统统实现,和实际开发并不相符
- 接下来,让我们了解一起实现的方法
多表查询:
Mapper
<resultMap type="domain.User" id="UserMap">
<id column="id" property="id"/>
<result column="password" property="password"/>
<result column="username" property="username"/>
<association property="banji" javaType="domain.Banji">
<id column="id" property="uid"/>
<result column="username" property="username"/>
<result column="banji" property="banji"/>
</association>
</resultMap>
<resultMap type="domain.User" id="UserList" extends="UserMap">
<id column="id" property="id"/>
<result column="password" property="password"/>
<result column="username" property="username"/>
<collection property="gardeList" ofType="domain.Garde">
<result column="garde" property="garde"/>
<result column="username" property="username"/>
</collection>
</resultMap>
<select id="findByIdAll" parameterType="int" resultMap="UserList">
select * from tb_user u,tb_garde g ,tb_banji b where u.id=g.id and u.id=b.uid and u.id=#{id}
</select>
测试
JoinUserDao joinUserDao=sqlSession.getMapper(JoinUserDao.class);
List<User> list=joinUserDao.findByIdAll(2);
System.out.println(list);
部分小结
- 其实这个多表查询很简单
- 代码也都是之前的代码,直接复制粘贴,只是我们需要注意一个关键字(extends)
- 多表查询也就是利用的(extends)实现的继承,继承与某个map,然后一起实现赋值
小结
- 表的关联关系介绍也就到这里了
- 这里介绍了一对一、一对多,相信多对多的实现也难倒不了你
- 这里具体的代码还是需要大家下去多练习练习