MyBatis3.1 学习教程

昨天中午,突然有想要学习 MyBatis 的冲动,经过 1.5 天的研究和学习,再加上以前学过 I batis

的经验,很快就了解了这门技术。 写这篇教程,是想告诉那些想学却又怕学习不好的同学们,

其实就这么简单,只要你用心了,就不怕学不好。还有一点,就是学习编程,不是看看文档

就 OK 了的,你需要去敲代码,去实践才行,切记,实践是检验真理的唯一标准!

一、准备工作

1.去官网下载 mybatis3.1 网址:blog.mybatis.org/

2.打开 eclipse,新建 java 项目,我建的是 mybatis,把下载的文件解压,打开文件夹找到

mybatis-3.1.0.jar 文件,把这个 jar 文件引入你的项目中

3.引入数据库驱动 jar, 我的是 mysql 数据库的驱动 mysql-connector-java -5.0.4-bin.jar

二、配置文件

1.在 src 源目录下,新建 sqlMapConfig.xml 文件,复制以下内容到 xml 文件中

<?xml version="1.0" encoding="UTF-8"  ?>

<!DOCTYPE  configuration  PUBLIC  "-//mybatis.org//DTD Config 3.0//EN"

        "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>

    <environments default="development">

        <environment id="development">

            <transactionManager type="JDBC"/>

            <dataSource type="POOLED">

                <property   name="driver"   value="com.mysql.jdbc.Driver"/>

                <property name="url"

                          value="jdbc:mysql://localhost:3306/mybatis?useUnicode=true&chara

cterEncoding=UTF-8"/>

                <property name="username" value ="root"/>

                <property name="password" value ="root"/>

            </dataSource>

        </environment>

    </environments>

    <mappers>

    </mappers>

</configuration>

有过框架学习经验的人肯定可以看出来,dataSource元素内,是用来配置数据源

的,你需要改的地方是driverurlusernamepassword

2.建数据库表,我使用的是EMP(员工)表和DEPT(部门)表,建表语句如下:

DROP TABLE IF EXISTS `emp`;

CREATE TABLE `emp` (

`empno` int(10) NOT NULL auto_increment,

`ename` varchar(30) NOT NULL,

`job` varchar(15) NOT NULL,

`mgr` int(4) default NULL,

`hiredate` date NOT NULL,

`sale` double(7,0) NOT NULL,  

`comm` double(7,0) default NULL,

`deptno` int(10)

PRIMARY KEY (`empno`)

DROP TABLE IF EXISTS `dept`;

CREATE TABLE `dept` (

`deptno` int(10) NOT NULL auto_incre ment,

`dname` varchar(20) NOT NULL,

`location` varchar(30) default '',

PRIMARY KEY (`deptno`)

)

现在,我们向这两张表里插入数据:

INSERT INTO `emp` VALUES ('7369', 'SMITH', 'CLERK', '7902', '1980 -12-17', '800', null, '20');

INSERT INTO `emp` VALUES ('7499', 'ALLEN', 'SALESMAN', '7698', '1981 -02-20', '1600', '300', 

'30');

INSERT INTO `emp` VALUES ('7521', 'WARD', 'SAL ESMAN', '7698', '1981-02-22', '1250', '500', 

'30');

INSERT INTO `emp` VALUES ('7566', 'JONES', 'MANAGER', '7839', '1981 -04-02', '2975', null, 

'20');

INSERT INTO `emp` VALUES ('7654', 'MARTIN', 'SALESMAN', '7698', '1981 -09 -28', '1250', 

'1400', '30');

INSERT  INTO `emp` VALUES ('7698', 'BLAKE', 'MANAGER', '7839', '1981 -05-01', '2850', null, 

'30');

INSERT INTO `emp` VALUES ('7782', 'CL ARK', 'MANAGER', '7839', '1981 -06-09', '2450', null, 

'10');

INSERT INTO `emp` VALUES ('7788', 'SCOTT', 'ANALYST', '7566', '1987 -07-15', '3000', null, 

'20');

INSERT INTO `emp` VALUES ('7839', 'KING', 'PRESIDENT', null, '1981 -11-17', '5000', null, '10');

INSERT INTO `emp` VALUES ('7844', 'TURNER', 'SALESMAN', '7698', '1981 -09-08', '1500', '0', 

'30');

INSERT INTO `emp` VALUES ('7876',  'ADAMS', 'CLERK', '7788', '1987-07-13', '1100', null, '20');

INSERT INTO `emp` VALUES ('7900', 'JAMES', 'CLERK', '7698', '1981 -12-03', '950', null, '30');

INSERT INTO `emp` VALUES ('7902', 'FORD', 'ANALYST', '7566', '1981 -12-03', '3000', null, 

'20');

INSERT INTO `emp` VALUES ('7934', 'MILLER', 'CLERK', '7782', '1982-01-23', '1300', null, '10');

INSERT INTO `dept` VALUES ('10', 'ACCOUNTING', 'NEW YORK');

INSERT INTO `dept` VALUES ('20', 'RESEARCH', 'DALLAS');

INSERT INTO `dept` VALUES ('30', 'SALES', 'CHICAGO');

INSERT INTO `dept` VALUES ('40', 'OPERATIONS', 'BOSTON');

数据库表我们建完了。

3.新建包,新建实体类,我的项目结构如下,可以模仿: 

我的实体类(javabean)名分别为 DeptEntityEmpEntity , 在 com.rogrand.entity 包下,内容

为:

package com.rogrand.entity;

import java.util.List;

public class DeptEntity {

private int deptno;//部门编号

private String dname;//部门名称

private String location;//部门所在地

//提供无参的构造方法和有参的构造方法,gettersetter方法

public DeptEntity() {

}

public DeptEntity(int deptno, String dname, String location) {  

this.deptno = deptno;

this.dname = dname;

this.location = location;

}

public int getDeptno() {

return deptno;

}

public void setDeptno( int deptno) {

this.deptno = deptno;

}

public String getDname() {

return dname;

}

public void setDname(String dname) {

this.dname = dname;

}

public String getLocation() {

return location;

}

public void setLocation(String location) {

this.location = location;

}

EmpEntity 

package com.rogrand.entity;

import java.util.Date;

/**

*

* @author scofield.hello

*/

public class EmpEntity {

private int empno;//员工编码

private String ename;//员工名称 

private String job;//职位

private int mgr;//上级编号

private Date hiredate;//入职时间

private double sale;//工资

private double comm;//奖金

public EmpEntity() {

}

public EmpEntity(int empno, String ename, String job, int mgr, 

Date hiredate, double sale, double comm) {

this.empno = empno;

this.ename = ename;

this.job = job;

this.mgr = mgr;

this.hiredate = hiredate;

this.sale = sale;

this.comm = comm;

}

public  EmpEntity(String ename, String job,  int  mgr, Date hiredate,

double sale, double comm) {

super();

this.ename = ename;

this.job = job;

this.mgr = mgr;

this.hiredate = hiredate;

this.sale = sale;

this.comm = comm;

}

public double getComm() {

return comm;

}

public void setComm(double comm) {

this.comm = comm;

}

public int getEmpno() {

return empno;

}

public void setEmpno(int empno) {

this.empno = empno;

}

public String getEname() {

return ename;

}

public void setEname(String ename) {

this.ename = ename;

}

public Date getHiredate() {

return hiredate;

}

public void setHiredate(Date hiredate) {

this.hiredate = hiredate;

}

public String getJob() {

return job;

}

public void setJob(String job) {

this.job = job;

}

public int getMgr() {

return mgr;

}

public void setMgr(int mgr) {

this.mgr = mgr;

}

public double getSale() {

return sale;

}

public void setSale(double sale) {

this.sale = sale;

}

有人可能会问,为什么员工跟部门之间没有对应关系呢?别急嘛,照顾一下新手,

关联关系我们下面会讲到的。

4.新建包com.rogrand.dao,新建两个接口IEmpMapperIdeptMapper,我们在里

面定义方法

package com.rogrand.dao;

import com.rogrand.entity.EmpEntity;

import java.util.List;

public interface IEmpMapper {

public int addNew(EmpEntity emp);

public int update(EmpEntity emp);

public int delete(EmpEntity emp);

public EmpEntity getEmp(int id);

public List<EmpEntity> getEmpList();

}

package com.rogrand.dao;

import java.util.List;

import com.rogrand.entity.DeptEntity;

public interface IDeptMapper {

public int addDept(DeptEntity dept);

public int deleteDept(DeptEntity dept);

public int updateDept(DeptEntity dept);

public DeptEntity getDept(int deptno);

public List<DeptEntity> getDeptList();

明白了吧,这两个接口定义了针对这两个实体的增删改查(GRUD)的方法, 通俗的说

就是针对EmpDept两张表的增删改查操作。

5.现在我们来改一改sqlMapConfig.xml文件,我们在configuration标签内,声明

EmpEntityDeptEntity对象,注意,这两个对象的别名在整个mybatis项目中的

xml文件中都可以使用。配置如下:

<typeAliases>

<typeAlias alias="Emp"

type="com.rogrand.entity.EmpEntity"></typeAlias>

<typeAlias alias="Dept"

type="com.rogrand.entity.DeptEntity" ></typeAlias>

</typeAliases>

需要注意的是,typeAliases标签和environments元素是平级关系。Type 是实体

类的完整类名,alias是实体类的别名。

6.配置sql映射文件,我们现在拿针对EmpEntity的操作来做一个示例。我们在

IEmpMapperIdeptMapper这两个接口所在的包下新建一个名称为

EmpMapper.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.rogrand.dao.IEmpMapper">

<!—这里写sql语句-->

</mapper>

定义完EmpMapper.xml文件后,要在sqlMapConfig.xml文件中引入:

<configuration>

…………..

<mappers>

<mapper resource="com/rogrand/dao/EmpMapper.xml"/>

</mappers>

</configuration>

namespace指的是命名空间,值为IEmpMapper接口的完整类名。 现在我们在mapper

标签内写sql语句,实现接口的各个方法。

查询:

<!-- 查询单个对象  -->

<select id="getEmp" parameterType="_int" resultType="Emp">

SELECT * FROM EMP WHERE EMPNO = #{id}

</select>

I d 代表的是这个查询的唯一标示,注意,要跟接口中对应的方法名是一致的

ParameterType 代表的是参数类型,比如,我们现在这个查询语句是根据 emp 表的主键

来查询一条信息,我们要传的参数是 id, id 是 int 类型的,所以我们的 paramterType=”int”

仔细的人可能会问, 为什么你的是_int 而不是 int 呢?_int 是 mybatis 框架定义的针对 int

类型数据的类型,当然,你不想这么写,写成 int 也是完全可以的。

resultType 指的是返回结果类型,我们写为 Emp,也就是前面我们在 sqlMapConfig.xml

文件中配置的 typeAlias 的别名

7.现在,我们使用 junit4 来对这个方法进行测试,junit4 会用吧?不会的话自己去查一下,  

这里就不做介绍了。

我们新建一个源文件夹,名为 junit,在这个文件夹下新建包 com.rogrand.entity。在包

里新建一个 junit 测试类,名为 EmpTest.java, 我们声明一个 org.apache.ibatis

.session.SqlSessionFactory 类的静态对象

private static SqlSessionFactory sqlMapper = null;

我们接着来生成一个名为setUpClass的方法,看下面的代码:

@BeforeClass

public static void setUpClass() throws Exception {

try{

String resource = "sqlMapConfig.xml";

Reader reader = Resources.getResourceAsReader(resource);

sqlMapper = new SqlSessionFactoryBuilder().build(reader);

reader.close();

}catch(Exception e){

e.printStackTrace();

}

}

这个方法上有一个@BeforeClass注解,这表明,这个方法会在类实例化之前加载,我

们用org.apache.ibatis.io.Resources类来加载sqlMapCnfig.xml文件,并得到

SqlSessionFactory对象的实例, Reader类也是org.apache.ibatis.io包里的。

接着,我们来写测试方法,测试我们的查询语句

@Test

public void testGetEmp(){

SqlSession session =  null;

try{

//打开session

session = sqlMapper.openSession();

//得到映射接口IempMapper

IEmpMapper mapper = session.getMapper(IEmpMapper.class);

//调用接口的getEmp方法

EmpEntity entity = mapper.getEmp(7369);

System.out.println(entity.getEname());

}catch (Exception e){

e.printStackTrace();

}finally{

session.close();

}

}

Mybatis会自动的调用idgetEmpsql语句,并且把查询的结果集ResultSet 

动注入到EmpEntity对象中,看看,是不是打印出来了员工名?对了,还有很重要

的一件事要告诉你,那就是要在最后关闭SqlSession对象,切记sessin的生命周

期是与这个方法保持一致的,方法执行完毕,关闭session。如果你的实体里的属

性名与数据库中Emp表的列名不一致的话,这时就要用到resultMap了。我们需要

EmpMapper.xml文件的mapper标签内配置一个resultMap,并且改select标签

内的resultTyperesultMap=”resultMapID”,具体如下:

<mapper namespace="com.rogrand.dao.IEmpMapper">

<!-- 基本的结果集  -->

<resultMap type="Emp" id="EMP_RESULTMAP_BASE">

<id column="empno" property="empno"/>

<result column="ename"  property="ename"/>

<result column="job" property="job"/>

<result column="hiredate" property="hiredate"/>

<result column="mgr" property="mgr"/>

<result column="sale" property="sale"/>

<result column="comm" property="comm"/>

</resultMap>

<!—这里写sql语句-->

<select id="getEmp" parameterType="_int" resultMap=" 

EMP_RESULTMAP_BASE ">

SELECT * FROM EMP WHERE EMPNO = #{id}

</select>

</mapper>

resuleMapid标签代表EmpEntity的主键,column的值为数据库的字段名

property代表EmpEntity中定义的与Emp表主键进行映射的属性名

result代表EmpEntity中的其他属性与表Emp的映射, mybatis框架会根据column

property自动将查出来的数据注入到EmpEntity对象中,当然, mybatis还支持

使用别名,例如,SELECT _ID  AS EMPNO,_ENAME AS ENAME …只需要改一下result

里面的column即可。

增加数据:

同样的,我们需要在sql映射文件中配置sql

··<!--  增加一条数据  -->

<insert id="addNew" parameterType="Emp">

INSERT INTO EMP (empno ,ename,job,mgr,hiredate,sale,comm) 

VALUES(default,#{ename },#{job},#{mgr},#{hiredate},

#{sale},#{comm})

</insert>

我们在测试方法中通过上述的方法,通过IempMapper来调用addNew方法,参数为

一个EmpEntity对象即可。增加成功返回1,不成功为0,删除,修改,增加调用完

毕后都需要提交,否则会自动回滚,使用session.commit()方法提交

public void testAddNew(){

SqlSession session = null;

try {

session = sqlMapper.openSession();

IEmpMapper mapper = session.getMapper(IEmpMapper.class);

EmpEntity emp = new EmpEntity("JOHN" , "DEVERLOPER", 7936,  

new Date(), 7000, 1000);

System.out.println(mapper.addNew(emp));

session.commit();

} catch (Exception e) {

e.printStackTrace();

}finally{

session.close();

}

}

修改操作:

<!-- 修改一条数据  -->

<update id="update" parameterType="Emp">

UPDATE EMP SET ENAME=#{ename},JOB=#{job},MGR=#{mgr},HIREDATE=

#{hiredate},SALE=#{sale},COMM=#{comm} WHERE EMPNO=#{empno}

</update>

测试方法为:

public void testUpdate(){

SqlSession session = null;

try {

session = sqlMapper.openSession();

IEmpMapper mapper = session.getMapper(IEmpMapper.class);

EmpEntity emp = new EmpEntity(7937,"HARRY", "DEVERLOPER", 

7936, new Date(), 6000, 500);

System.out.println(mapper.update(emp));

session.commit();

} catch (Exception e) {

e.printStackTrace();

}finally{

session.close();

}

}

删除操作:

<!-- 删除一条数据  -->

<delete id="delete" parameterType="Emp">

DELETE FROM EMP WHERE EMPNO = #{empno}

</delete>

public void testDelete(){

SqlSession session = null;

try {

session = sqlMapper.openSession();

IEmpMapper mapper = session.getMapper(IEmpMapper.class);

EmpEntity emp = new EmpEntity(7937); 

System.out.println(mapper.delete(emp));

session.commit();

} catch (Exception e) {

e.printStackTrace();

}finally{

session.close();

}

}

对于上述比较简单单一的增删改查操作,mybatis提供了简单的注解方式,供我们

使用,我们不再需要去EmpMapper.xml文件中定义selectupdatedelete

insert,只需要在IempMapper接口中的方法上面是用相应的注解,例如查询

@Sel ect("SELECT    *    FROM    EMP    WHERE    EMPNO  = #{i d}") 

public EmpEntity getEmp(int id);

同样,调用这个getEmp方法即可触发上面的查询语句的执行

三、高级查询

有时你会发现,简单的查询方式可能无法满足我们的需要,这时,我们就需要使用

高级查询方式。

1.  我们在EmpEntity中再声明一个DeptEntity类型的属性,提供getter

setter方法,并且生成带有所有属性参数的构造方法

private DeptEntity dept;

public EmpEntity(String ename, String job, int mgr,

Date hiredate,  double  sale,  double   comm, DeptEntity dept) {

super();

this.ename = ename;

this.job = job;

this.mgr = mgr;

this.hiredate = hiredate;

this.sale = sale;

this.comm = comm;

this.dept = dept;

}

public DeptEntity getDept() {

return dept;

}

public void setDept(DeptEntity dept) {

this.dept = dept;

}

DeptEntity属性在这里代表的是一个员工对应与一个部门,在Emp表中,

deptnoemp表与dept表进行连接的唯一纽带,即外键

现在我们来查询带有部门的所有员工信息,在IEmpMapper接口中定义方法 

public List<EmpEntity> getEmpListJoinDept();

配置sql映射文件中对于这条查询的结果集

<!-- 多表联合查询时定义的resultMap  -->

<resultMap type="Emp" id="EMP_RESULTMAP" extends=" 

EMP_RESULTMAP_BASE" >

<id column="empno" property="empno"/>

<result column="ename"  property="ename"/>

<result column="job" property="job"/>

<result column="hiredate" property="hiredate"/>

<result column="mgr" property="mgr"/>

<result column="sale" property="sale"/>

<result column="comm" property="comm"/>

<association property="dept"  column="deptno"

javaType="Dept" resultMap="DEPT_RESULTMAP_BASE"></association>

</resultMap>

结果集也可以继承,是的,这为我们提供了很大的方便。

association代表关联,property代表EmpEntity中的关联对象的属性名,

column="deptno"代表EmpEntityDeptEntity之间是通过emp表的deptno

关联的,也就是外键关联,javaType是这个属性的java类型,可以不写,

mybatis会自己找到,resultMap="DEPT_RESULTMAP_BASE"指的是dept这个

属性的值用的结果集是哪个。 我们在DeptMapper.xml文件中可以配置这样一个

结果集:

<resultMap type="dept"  id="DEPT_RESULTMAP_BASE">

<id column="deptno" property="deptno"/>

<result column="dname"  property="dname"/>

<result column="location" property="location"/>

</resultMap>

那我们的sql语句应该怎么写呢?

<!-- emp关联查询dept -->

<select  id="getEmpListJoinDept" resultMap="EMP_RESULTMAP">

SELECT * FROM EMP E LEFT OUTER JOIN DEPT D ON E.DEPTNO = D.DEPTNO

</select>

测试方法为:

@Test

public void testGetEmpListJoinDept(){

SqlSession session = null;

try {

session = sqlMapper.openSession();

IEmpMapper mapper = session.getMapper(IEmpMapper.class);

List<EmpEntity> emps = mapper.getEmpListJoinDept();

for(EmpEntity emp : emps){

System.out.print(emp.getEmpno() + "||");

System.out.print(emp.getEname() + "||"); 

System.out.print(emp.getJob() + "||");

System.out.print(emp.getMgr() + "||");

System.out.print(emp.getHiredate() + "||");

System.out.print(emp.getSale() + "||");

System.out.print(emp.getComm() + "||");

if(emp.getDept() != null){

System.out.print(emp.getDept().getDname());

}

System.out.println();

} catch (Exception e) {

e.printStackTrace();

}finally{

session.close();

}

}

现在我们增加一条带有部门编号的员工信息:

IempMapper接口定义方法:

public int addEmpEntity(EmpEntity emp);

SQL:

<insert id="addEmpEntity" parameterType="Emp">

INSERT INTO EMP (empno,ename,job,mgr,hiredate,sale,comm,deptno) 

VALUES(default,#{ename },#{job},#{mgr},#{hiredate},#{sale},

#{comm},#{dept.deptno})

</insert>

dept.deptno代表的是EmpEntitydept属性的deptno属性的值。

测试:

public void testAddNew(){

SqlSession session = null;

try {

session = sqlMapper.openSession();

IEmpMapper mapper = session.getMapper(IEmpMapper.class);

DeptEntity dept = new DeptEntity(50,"SDS","中国武汉光谷软件

");

EmpEntity emp = new EmpEntity("JOHN" , "DEVERLOPER", 7936,

new Date(), 7000, 1000,dept);

System.out.println(mapper.addEmpEntity(emp));

session.commit();

} catch (Exception e) {

e.printStackTrace();

}finally{

session.close();

}

2.多对一查询

DeptEntity中加入下面的属性,代表一个部门里有多个员工

private List<EmpEntity> emps; 

提供gettersetter方法,构造方法

IdeptMapper接口中定义方法:

public DeptEntity  getDeptJoinEmp(int  deptno);//根据deptno

public DeptEntity getDeptJoinEmp2(int deptno);

方法一:嵌套查询

我们在DeptMapper.xml文件中配置一个IDDEPT_RESULTMAP_SUB的结果集:

<!-- 部门  员工  一对多  结果集--><!--  一对多关系时不推荐使用这种嵌套查询

的方式  -->

<resultMap type="Dept" id="DEPT_RESULTMAP_SUB"

extends="DEPT_RESULTMAP_BASE">

<collection  property="emps"  javaType="java.util.List"  ofType="Emp"

select="com.rogrand.dao.IEmpMapper.getEmpListByDeptno">

</collection>

</resultMap>

这个结果集继承与DEPT_RESULTMAP_BASE,这个我们在上面已经配置过了。

colllection代表的是集合,是指一对多的关系,property是集合类型的属性名

ofType代表的是集合中元素的类型,select=”

com.rogrand.dao.IEmpMapper.getEmpListByDeptno”

指的是每当查询完一次dept表后,再去IempMapper接口中调用

getEmpListByDeptno方法,根据部门查询员工列表

SQL中配置

<!-- dept嵌套查询emp --><!--  不推荐使用嵌套查询  -->

<select id="getDeptJoinEmp" parameterType="_int"

resultMap="DEPT_RESULTMAP_SUB">

SELECT * FROM DEPT WHERE DEPTNO = #{ deptno}

</select>

测试方法为:

public void testGetDeptListJoinEmp(){

SqlSession session = null;

try {

session = sqlMapper.openSession();

IDeptMapper mapper = session.getMapper(IDeptMapper. class);

DeptEntity dept = mapper.getDeptJoinEmp(30);

List<EmpEntity> emps = dept.getEmps();

System.out.print(dept.getDeptno() +  "||");

System.out.print(dept.getDname() + "||");

System.out.print(dept.getLocation());

System.out.println("--------------------------"); 

for(EmpEntity emp : emps){

System.out.print(emp.getEmpno() + "||");

System.out.print(emp.getEname() + "||");

System.out.print(emp.getJob() + "||");

System.out.print(emp.getMgr() + "||");

System.out.print(emp.getHiredate() + "||");

System.out.print(emp.getSale() + "||");

System.out.print(emp.getComm());

System.out.println();

} catch (Exception e) {

e.printStackTrace();

}finally{

session.close();

}

}

方法二:嵌套结果

配置结果集:

<!-- 部门  员工  一对多  结果集--><!--  推荐使用嵌套结果  -->

<resultMap type="Dept" id="DEPT_RESULTMAP_JOIN"  

extends="DEPT_RESULTMAP_BASE">

<collection property="emps" ofType="Emp"

resultMap="com.rogrand.dao.IEmpMapper.EMP_RESULTMAP_BASE">

</collection>

</resultMap>

看到没,这个collection中嵌套的是结果集,这是mybatis推荐的用法,

SQL:

<!-- dept嵌套结果  --><!--  推荐使用嵌套结果  -->

<select id="getDeptJoinEmp2" parameterType="_int" 

resultMap="DEPT_RESULTMAP_JOIN">

SELECT * FROM DEPT D LEFT OUTER JOIN EMP E ON D.DEPTNO = E.DEPTNO 

WHERE D.DEPTNO = #{deptno}

</select>

测试方法:

@Test

public void testGetDeptListJoinEmp2(){

SqlSession session = null;

try {

session = sqlMapper.openSession();

IDeptMapper mapper = session.getMapper(IDeptMapper. class);

DeptEntity dept = mapper.getDeptJoinEmp2(30);

List<EmpEntity> emps = dept.getEmps();

System.out.print(dept.getDeptno() +  "||"); 

System.out.print(dept.getDname() + "||");

System.out.print(dept.getLocation());

System.out.println("--------------------------");

for(EmpEntity emp : emps){

System.out.print(emp.getEmpno() + "||");

System.out.print(emp.getEname() + "||");

System.out.print(emp.getJob() + "||");

System.out.print(emp.getMgr() + "||");

System.out.print(emp.getHiredate() + "||");

System.out.print(emp.getSale() + "||");

System.out.print(emp.getComm());

System.out.println();

} catch (Exception e) {

e.printStackTrace();

}finally{

session.close();

}

}

好了,大家学到这里可以说是基本入门了以后的学习也会相当的轻松, 官方的中文文档

翻译的还是不错的,大家可以去下载一份,后面的更高级的资料都在里面,也非常的详

,大家可以仔细研读。我就写到这里吧,希望这份文档能给大家带来帮助,这是我衷

心希望的,如果有什么不懂或这有什么想跟我探讨的,大家可以加我  877379683

原文地址:https://www.cnblogs.com/sand-tiny/p/mybatis-3-1.html