什么是一对一的关系?比如一个人有一个身份证,反过来,一个身份证对应一个人,这就是一对一的关系。见下图
比如在人表中有一个人: 编号为1,姓名为宋江,身份证号在本表中并不真实的存放,它只是存放身份证号在另一个表中的对应编号(如对应的编号为3),
你可以理解为: 1号 宋江 它的身份证号是对应表中的第3号记录。
像这样的关系,我们在数据库中可以用两个表来实现,一个人表(aaaa_person),一个身份证表(aaaa_card),这两个表是通过人表中的身份证编号和身份证表中的身份证编号关联起来的,
注:在person和card的前面加aaaa_是为了区别其它工程的数据表用的。比如aaaa_person表示是aaaa工程要使用的数据表,bbbb_stu表示是bbbb工程要使用的数据表,
如何通过一个人的id号将这个人的信息查询出来呢?我们常用这条SQL语句:
select * from aaaa_person where id=’1′
结果是: id name sex age card_id
1 宋江 男 26
但此条语句查询出来的身份证编号部分它不是真正的身份证号,而是另一个表中的记录,所以不是我们想要的。
将SQL语句改为:
select p.id,p.name,p.sex,p.age,c.`code`
from aaaa_person p, aaaa_card c
where p.card_id=c.id and p.id=’1′
结果是: id name sex age code
1 宋江 男 26 420302196503433346
关键是:我只想用 select * from aaaa_person where id=’1′ 查出后面的这个结果。
那么用mybatis如何实现呢?
对于这种一对一的关系,可以用association来实现,在PersonDao.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.jintingbo.dao.PersonDao">
<select id="selectPersonById" parameterType="int" resultMap="personMapper">
select * from aaaa_person where id=#{id}
</select>
<resultMap type="com.jintingbo.pojo.Person" id="personMapper">
<id property="id" column="id" />
<result property="name" column="name" />
<result property="sex" column="sex" />
<result property="age" column="age" />
<association property="card" column="card_id"
select="com.jintingbo.dao.CardDao.selectCardById"
javaType="com.jintingbo.pojo.Card" />
</resultMap>
</mapper>
下面我对上面的这种写法做详细的解说:
<mapper namespace=”com.jintingbo.dao.PersonDao”>
这一句表示我下面的操作是针对com.jintingbo.dao.PersonDao这个接口而言的;
<select id=”selectPersonById” parameterType=”int” resultMap=”personMapper”> select * from aaaa_person where id=#{id} </select>
这一句中select标签表示我要进行的操作是一个查询操作;
id:表示我这个是查询操作的中编号。对一个表的查询操作可能有好几个,所以用id号进行区分;同时它也对应PersonDao这个接口中的方法名。
parameterType=”int” 表示我进行查询操作时,我传入的参数是个int类型;同时它也对应PersonDao这个接口中selectPersonById方法的参数;
resultMap=”personMapper” : resultMap表示是mybatis自己定义的一个类型,为什么要自定义类型呢?因为java代码中没有一个pojo类型与我这条SQL语句要返回的类型相符,所以,我mybaits只好自定义一个类型,personMapper就是这个类型的id号。
select * from aaaa_person where id=#{id} :这一条就是SQL的查询语句了,你看它只查询了aaaa_person表(即人表),并没有查询aaaa_card表(即身份证表); 那么它又是如何得到另一个表中身份证的具体数字的呢?神奇就在这里,它是通过
下面的 resultMap 标签得到的,resultMap代码如下:
<resultMap type="com.jintingbo.pojo.Person" id="personMapper">
<id property="id" column="id" />
<result property="name" column="name" />
<result property="sex" column="sex" />
<result property="age" column="age" />
<association property="card" column="card_id"
select="com.jintingbo.dao.CardDao.selectCardById"
javaType="com.jintingbo.pojo.Card" />
</resultMap>
在resultMap标签中有一个association标签,它就是专门来表现这种一对一关系的,代码如下:
<association property="card" column="card_id"
select="com.jintingbo.dao.CardDao.selectCardById"
javaType="com.jintingbo.pojo.Card" />
上面这个标签的意思是:你java中Person中的card属性,在数据表中是通过字段card_id与aaaa_card表示相关联的,你将用CardDao中的selectCardById方法去查询,查询的结果返回的是一个Card的java类型。
至于:
<id property="id" column="id" />
<result property="name" column="name" />
<result property="sex" column="sex" />
<result property="age" column="age" />
就比较好理解了,
<id>标签是必须要的,它表示我Person类中的id属性,是与数据集中id字段相对应的,
<result>它表示我Person类中的name属性,是与数据集中name字段相对应的。
其它几个<result>标签是差不多一样的意思。
下面我就在SSM框架下,分步操作:
目的:在页面上输入一个人的id号,得到这个人的全部真实信息。
第一步:搭建好SSM框架(略)
第二步:写一个前端的JSP页面,表示我们要干什么!
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>
<%
String path = request.getContextPath();
String basepath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
%>
<html>
<head>
<base href="<%=basepath %>"/>
<meta charset="utf-8"/>
<title>Insert title here</title>
</head>
<body>
<form action="psfz" method="post">
请输入人的id号:<input type="text" id="id" name="id" /><br />
<input type="submit" id="btn" name="btn" value="提交" />
<input type="reset" id="rebtn" name="rebtn" value="重置" />
</form>
</body>
</html>
第三步:在Dao包中写PersonDao.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.jintingbo.dao.PersonDao">
<select id="selectPersonById" parameterType="int" resultMap="personMapper">
select * from aaaa_person where id=#{id}
</select>
<resultMap type="com.jintingbo.pojo.Person" id="personMapper">
<id property="id" column="id" />
<result property="name" column="name" />
<result property="sex" column="sex" />
<result property="age" column="age" />
<association property="card" column="card_id"
select="com.jintingbo.dao.CardDao.selectCardById"
javaType="com.jintingbo.pojo.Card" />
</resultMap>
</mapper>
第四步:在Dao包中写Person表的Dao接口, 注意接口名称一定是PersonDao,与上面PersonDao.xml中的PersonDao相同。
package com.jintingbo.dao;
import com.jintingbo.pojo.Person;
public interface PersonDao {
Person selectPersonById(Integer id);
}
第五步:因为在person表中有关联card表的查询,所以你还要在Dao中写接口和操作映射:
在Dao包中写CardDao.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.jintingbo.dao.CardDao">
<!--以id号进行查询-->
<select id="selectCardById" parameterType="int" resultType="com.jintingbo.pojo.Card">
select * from aaaa_card where id=#{id}
</select>
</mapper>
在Dao包中写CardDao接口,注意Dao中接口与操作的两个文件名要相同。
package com.jintingbo.dao;
import com.jintingbo.pojo.Card;
public interface CardDao {
Card selectCardById(Integer id);
}
第六步:在service包中写服务接口和服务实现,注意服务实现的包要在service包中再建一个impl包
接口如下:
package com.jintingbo.service;
import com.jintingbo.pojo.Person;
public interface PersonService {
Person selectPersonById(Integer id);
}
第七步:在service包下的impl包中写服务的实现:
package com.jintingbo.service.impl;
import com.jintingbo.dao.PersonDao;
import com.jintingbo.pojo.Person;
import com.jintingbo.service.PersonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class PersonServiceImpl implements PersonService {
@Autowired
PersonDao personDao;
@Override
public Person selectPersonById(Integer id) {
Person person=personDao.selectPersonById(id);
return person;
}
}
第八步:在controller中写控制代码,因为是要通过人来查询身份证号,所以只需要写PersonController就可以了。
package com.jintingbo.controller;
import com.jintingbo.pojo.Card;
import com.jintingbo.pojo.Person;
import com.jintingbo.service.CardService;
import com.jintingbo.service.PersonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class PersonController {
@Autowired
CardService cardService;
@Autowired
PersonService personService;
@RequestMapping(value = "/psfz")
public ModelAndView sfz(Integer id){
Person person=personService.selectPersonById(id);
ModelAndView mv=new ModelAndView();
mv.setViewName("person/person");
mv.addObject("person",person);
return mv;
}
}
第九步:因为在Controller层中有值要返回前端,所以要在前端新建一个person目录,再在目录下新建一个person.jsp文件,代码如下:
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>
<%
String path = request.getContextPath();
String basepath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
%>
<html>
<head>
<base href="<%=basepath %>"/>
<meta charset="utf-8"/>
<title>Insert title here</title>
</head>
<body>
<h1>person</h1>
${person}
</body>
</html>
第十步:完毕!
此处应该有掌声和评论!
附工程目录图: