CREATE TABLE teacher( t_id INT PRIMARY KEY AUTO_INCREMENT, t_name VARCHAR(20) ); CREATE TABLE class( c_id INT PRIMARY KEY AUTO_INCREMENT, c_name VARCHAR(20), teacher_id INT ); ALTER TABLE class ADD CONSTRAINT fk_teacher_id FOREIGN KEY (teacher_id) REFERENCES teacher(t_id); INSERT INTO teacher(t_name) VALUES('LS1'); INSERT INTO teacher(t_name) VALUES('LS2'); INSERT INTO class(c_name, teacher_id) VALUES('bj_a', 1); INSERT INTO class(c_name, teacher_id) VALUES('bj_b', 2);
如上的sql可见,这里是一个一对一的表,一个老师,对应一个班级,那么,如果要用sql,把班级信息查出来(包含老师信息),那我们可以这样查:
方法一:
SELECT * FROM class c,teacher t WHERE c.teacher_id=t.t_id AND c.c_id=1
方法二:
select * from class where c_id=1 select * from teacher where t_id=1
Class实体类:
public class Classes { private int id; private String name; private Teacher teacher; } ..省略了get set方法,及默认构造方法
Teacher实体类:
public class Teacher { private int id; private String name; } 省略了get set方法,及空构造方法
在实体类中也是可以看到的,Classes类中有着Teacher属性,所以这就是一个一对一的一个写法,所以在配置文件中,也要把这种关系给表达出来,下面给出配置文件的写法:
<?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="zxj.domain.ClassMapper"> <!-- 根据id来查询班级信息(带老师的信息) --> <!-- 查询方法sql:SELECT * FROM class c,teacher t WHERE c.teacher_id=t.t_id AND c.c_id=1 --> <select id="getClass" parameterType="int" resultMap="getClassMap"> SELECT * FROM class c,teacher t WHERE c.teacher_id=t.t_id AND c.c_id=#{id} </select> <!-- 在返回的结果集中,指定每一个列,对应的是哪一个对象,使用association标签来声明其它的对象,即一对一 --> <resultMap type="zxj.domain.Classes" id="getClassMap"> <id property="id" column="c_id"/> <result column="c_name" property="name"/> <association property="teacher" javaType="zxj.domain.Teacher"> <id property="id" column="t_id"/> <result property="name" column="t_name"/> </association> </resultMap> </mapper>
在上面的配置文件中,使用<resultMap>标签,可以把数据库中每一个字段,与java实体类中的字段对应,然后MyBaits就会知道它们的关系,然后就封装成对象。
下面来做一个测试:
/** * 测试一对一的查询<br> * 查询sql:SELECT * FROM class c,teacher t WHERE c.teacher_id=t.t_id AND c.c_id=1 */ @Test public void testOneToOne() { InputStream in = TestMybaits.class.getClassLoader().getResourceAsStream("conf.xml"); SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in); SqlSession session = factory.openSession(); String statement = "zxj.domain.ClassMapper.getClass"; Classes c = session.selectOne(statement, 1); System.out.println(c); session.close(); }
使用的方法还是如平常的使用是一样的
配置文件的写法:
<?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="zxj.domain.ClassMapper"> <!-- 另一种查询一对一的方法 --> <!-- 方法二:select * from class where c_id=1 select * from teacher where t_id=1(这里的t_id是上一条sql得到的id) --> <select id="getClass2" parameterType="int" resultMap="getClassMap2"> select * from class where c_id=#{id} </select> <select id="getTeacher" parameterType="int" resultType="zxj.domain.Teacher"> <!-- 这里需要取别名,因为数据库中的字段,与实体类中的字段不一至,我们需要让它一至,才能封装成对象 --> select t_id id,t_name name from teacher where t_id=#{id} </select> <resultMap type="zxj.domain.Classes" id="getClassMap2"> <id column="c_id" property="id"/> <result column="c_name" property="name"/> <!-- 实现原理是查询两次sql,第二次查询的条件是根据第一次查询的结果,下面的column属性就是要传过去查询的参数 --> <association property="teacher" column="teacher_id" select="getTeacher" > </association> </resultMap> </mapper>
它是要发出两条sql,第一条sql查class,第二条sql查teacher,但是第二条sql的条件是根据第一条sql查出的结果作为条件的。
测试:
/** * 方式二<br> * 测试一对一的查询<br> * 查询sql:SELECT * FROM class c,teacher t WHERE c.teacher_id=t.t_id AND c.c_id=1 */ @Test public void testOneToOne2() { InputStream in = TestMybaits.class.getClassLoader().getResourceAsStream("conf.xml"); SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in); SqlSession session = factory.openSession(); String statement = "zxj.domain.ClassMapper.getClass2"; Classes c = session.selectOne(statement, 1); System.out.println(c); session.close(); }
这样就完成了一对一的查询。