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元素内,是用来配置数据源
的,你需要改的地方是driver、url、username、password。
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)名分别为 DeptEntity、EmpEntity , 在 com.rogrand.entity 包下,内容
为:
package com.rogrand.entity;
import java.util.List;
public class DeptEntity {
private int deptno;//部门编号
private String dname;//部门名称
private String location;//部门所在地
//提供无参的构造方法和有参的构造方法,getter和setter方法
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,新建两个接口IEmpMapper和IdeptMapper,我们在里
面定义方法
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)的方法, 通俗的说
就是针对Emp和Dept两张表的增删改查操作。
5.现在我们来改一改sqlMapConfig.xml文件,我们在configuration标签内,声明
EmpEntity和DeptEntity对象,注意,这两个对象的别名在整个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的操作来做一个示例。我们在
IEmpMapper和IdeptMapper这两个接口所在的包下新建一个名称为
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会自动的调用id为getEmp的sql语句,并且把查询的结果集ResultSet 自
动注入到EmpEntity对象中,看看,是不是打印出来了员工名?对了,还有很重要
的一件事要告诉你,那就是要在最后关闭SqlSession对象,切记sessin的生命周
期是与这个方法保持一致的,方法执行完毕,关闭session。如果你的实体里的属
性名与数据库中Emp表的列名不一致的话,这时就要用到resultMap了。我们需要
在EmpMapper.xml文件的mapper标签内配置一个resultMap,并且改select标签
内的resultType为resultMap=”resultMap的ID”,具体如下:
<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>
resuleMap内id标签代表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文件中定义select、update、delete、
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表中,
deptno是emp表与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"代表EmpEntity和DeptEntity之间是通过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代表的是EmpEntity中dept属性的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;
提供getter和setter方法,构造方法
在IdeptMapper接口中定义方法:
public DeptEntity getDeptJoinEmp(int deptno);//根据deptno查
public DeptEntity getDeptJoinEmp2(int deptno);
方法一:嵌套查询
我们在DeptMapper.xml文件中配置一个ID为DEPT_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
MyBatis3.1 学习教程的更多相关文章
- Deep Learning 19_深度学习UFLDL教程:Convolutional Neural Network_Exercise(斯坦福大学深度学习教程)
理论知识:Optimization: Stochastic Gradient Descent和Convolutional Neural Network CNN卷积神经网络推导和实现.Deep lear ...
- WebPack 简明学习教程
WebPack 简明学习教程 字数1291 阅读22812 评论11 喜欢35 WebPack是什么 一个打包工具 一个模块加载工具 各种资源都可以当成模块来处理 网站 http://webpack. ...
- MyBatis入门学习教程-使用MyBatis对表执行CRUD操作
上一篇MyBatis学习总结(一)--MyBatis快速入门中我们讲了如何使用Mybatis查询users表中的数据,算是对MyBatis有一个初步的入门了,今天讲解一下如何使用MyBatis对use ...
- 深入浅出的javascript的正则表达式学习教程
深入浅出的javascript的正则表达式学习教程 阅读目录 了解正则表达式的方法 了解正则中的普通字符 了解正则中的方括号[]的含义 理解javascript中的元字符 RegExp特殊字符中的需要 ...
- 子类重载父类的方法“parent::方法名”转于 恩聪PHP学习教程
在PHP中不能定义重名的函数,也包括不能再同一个类中定义重名的方法,所以也就没有方法重载.单在子类中可以定义和父类重名的方法,因为父类的方法已经在子类中存在,这样在子类中就可以把从父类中继承过来的方法 ...
- LaTeX学习教程
本来我对LaTeX不是看好的,毕竟都是命令格式的.觉得有word就足够啦word可视化操作方便快捷. 但是由于要写论文等,在导师要求下潜心学习一下,不知不觉间被LaTeX的强大功能所吸引.现在很多出版 ...
- Deep Learning 13_深度学习UFLDL教程:Independent Component Analysis_Exercise(斯坦福大学深度学习教程)
前言 理论知识:UFLDL教程.Deep learning:三十三(ICA模型).Deep learning:三十九(ICA模型练习) 实验环境:win7, matlab2015b,16G内存,2T机 ...
- Deep Learning 12_深度学习UFLDL教程:Sparse Coding_exercise(斯坦福大学深度学习教程)
前言 理论知识:UFLDL教程.Deep learning:二十六(Sparse coding简单理解).Deep learning:二十七(Sparse coding中关于矩阵的范数求导).Deep ...
- Deep Learning 11_深度学习UFLDL教程:数据预处理(斯坦福大学深度学习教程)
理论知识:UFLDL数据预处理和http://www.cnblogs.com/tornadomeet/archive/2013/04/20/3033149.html 数据预处理是深度学习中非常重要的一 ...
随机推荐
- 测试一个函数的运行时间(C++)
#include <ctime> static clock_t Start,Finish; Start=clock(); fun(); Finish = clock(); double t ...
- 通过DeveloperApi获取spark程序执行进度及异常
在应用spark时,经常要获取任务的执行进度,可以参照jobProgressListener的设计来完成该功能. 以下代码仅供参考,欢迎交流. 效果显示: 代码: package org.apache ...
- Kooboo中主要的几个关键词中的关系
Kooboo中主要的几个关键词中的关系 Content Type //相当于数据库表 Content //相当于数据 View //部分View 她可以使用Content ...
- 查看目标文件是否是以-fPIC编译的, ar 打包命令将多个静态库打包到一个里面
readelf --relocs foo.o | egrep '(GOT|PLT|JU?MP_SLOT)' 上句大多数时候(和平台有关)可以正确判断是否是以fPIC选项编译的,如果输出为空,基本可以表 ...
- php升级到5.4
这里使用 Webtatic EL6的YUM源来安装php5.4,我们首页安装Webtatic EL6 YUM源 rpm -Uvh http://repo.webtatic.com/yum/el6/la ...
- UVALive 5111 Soccer Teams (动态规划)
题意:给指定数量的数字“1”,“2”,“3”……,“9”.用所有这些数字加上任意个0组成一个数,要求数能被11整除,且数的位数尽量小. 能被11整除的数有一个特点,奇数位数字之和与偶数位之和的差为11 ...
- vbs脚本发送邮件
NameSpace = "http://schemas.microsoft.com/cdo/configuration/"Set Email = CreateObject(&quo ...
- eclipse安装maven插件
- mac下firefox复制粘贴失效解决办法
现象:复制粘贴只能在firefox上操作,也就是其他应用内的内容无法复制到firefox,firefox的内容也无法复制其他应用,但是firefox自己的内容可以复制本身(比如各个tab页之间复制) ...
- sping获取bean方法 解决资源耗尽
// ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"applicationCon ...