MyBetis3.2框架技术

时间:2024-05-26 15:37:26

1.1    MyBatis介绍

MyBatis 世界上流行最广泛的基于SQ语句的ORM框架,由Clinton Begin 在2002 年创建,其后,捐献给了Apache基金会,成立了iBatis 项目。2010 年5 月,将代码库迁致Google Code,并更名为MyBatis.

1.2 与Hibernate比较

  1. 学习成本:MyBatis简单易学(特别是有SQL语法基础的人),较接近JDBC
  2. 程序灵活性:MyBatis直接使用SQL,灵活性高
  3. 程序执行效律:MyBatis效律高
  4. 可移植性:hibernate较好(与数据库关联在配置中完成,HQL语句与数据库无关)

1.3    适用场合

MyBatis是一个灵活的DAO层解决方案,满足较高的性能要求,可以在很多场合使用,但一般以下场合不建议使用:

  1. 需要支持多种数据库或数据库有移植要求
  2. 完全动态SQL,例如:字段都要动态生成

使用的不是关系数据库

1.4 开发步骤(推荐)

  1. 新建JAVA项目或WEB项目
  2. 部署jar包(包括数据库驱动包):使用MyBatis需要先下载jar包:下载地址http://code.google.com/p/mybatis
  3. 编写主配置文件
  4. 创建数据库及表
  5. 创建实体类及SQL映射文件
  6. 编写数据库接口及实现
  7. 编写测试类及测试

1.5 开发示例

1.5.1  新建项目

新建java项目或web 项目。

1.5.2 导入JAR包

导入mybatis和数据库驱动包、日志包(配置日志配置文件)。

1.5.3  创建myBatis-config.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">
<!--事务管理类型主要有jdbc和managed,前者依赖于数据源获得的连接,后者依赖于容器 -->
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<!-- 如果数据库设置为UTF-8,则URL参数连接需要添加?useUnicode=true&amp;characterEncoding=UTF-8,如下 -->
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useUnicode=true&amp;characterEncoding=UTF-8" />
<property name="username" value="***" />
<property name="password" value="***" />
</dataSource>
</environment>
</environments>
</configuration>

1.5.4  创建数据库及表

drop database if exists mybatis;
create database mybatis CHARACTER SET UTF8;
use mybatis; create table dept(
dept_id int primary key auto_increment,
dept_name varchar(50),
dept_address varchar(50)
); insert into dept(dept_name,dept_address) values('研发部一部','广州');
insert into dept(dept_name,dept_address) values('研发部二部','广州');
insert into dept(dept_name,dept_address) values('研发部三部','深圳');
select * from dept;

1.5.5  创建实体类:Dept.java

public class Dept implements Serializable {
private Integer deptId; //部门编号
private String deptName;//部门名称
private String deptAddress;//部门地址
public Integer getDeptId() {
return deptId;
}
public void setDeptId(Integer deptId) {
this.deptId = deptId;
}
public String getDeptName() {
return deptName;
}
public void setDeptName(String deptName) {
this.deptName = deptName;
}
public String getDeptAddress() {
return deptAddress;
}
public void setDeptAddress(String deptAddress) {
this.deptAddress = deptAddress;
}
@Override
public String toString() {
return "Dept [deptId=" + deptId + ", deptName=" + deptName
+ ", deptAddress=" + deptAddress + "]";
}
}

1.5.6  创建SQL映射文件及修改主配置文件

SQL映射文件:DeptMapper.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="cn.it.entity.DeptMapper">
<!-- 一般在查询时使用-->
<resultMap type="cn.it.entity.Dept" id="deptResultMap">
<id property="deptId" column="dept_id"/>
<result property="deptName" column="dept_name"/>
<result property="deptAddress" column="dept_address"/>
</resultMap>
<!-- 定义插入的sql语句,通过命名空间+id方式被定位 -->
<insert id="insert" parameterType="cn.it.entity.Dept">
insert into dept(dept_name,dept_address) values(#{deptName},#{deptAddress});
</insert>
</mapper> 修改myBatis-config.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">
…………
</environments> <mappers>
<mapper resource="cn/it/entity/DeptMapper.xml" />
</mappers> </configuration>

1.5.7  编写数据库操作

包括操作接口及实现,接口略,实现类为:DeptDaoImpl.java

public class DeptDaoImpl {
/**
* 用于插入数据到dept表。
* @param dept 部门信息
* @return 表示受影响的行数
*/
public int insert(Dept dept){
/*
* 1.读取配置信息
* 2.构建session工厂
* 3.创建session
* 4.启动事务(可选)
* 5.数据处理
* 6.提交事务、回滚事务(可选)
* 7.关闭session
*/
int i=0;
SqlSession session=null;
String config="myBatis-config.xml";
Reader reader = null;
try {
reader=Resources.getResourceAsReader(config);
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(reader);
session=sqlSessionFactory.openSession();
//事务默认自动启动
//SQL映射文件定义的命名空间+SQL语句的ID定位SQL语句,例如下的:cn.it.entity.DeptMapper.insert
i=session.insert("cn.it.entity.DeptMapper.insert",dept);
session.commit();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
session.rollback();
}finally{
//关闭reader对象,这里略
session.close();
}
return i;
}
}

1.5.8  编写测试类

需要导入junit包

public class DeptTest {
private static DeptDaoImpl deptDaoImpl;
@BeforeClass
public static void setUpBeforeClass() throws Exception {
deptDaoImpl=new DeptDaoImpl();
} @AfterClass
public static void tearDownAfterClass() throws Exception {
deptDaoImpl=null;
} @Test
public void testInsert() {
Dept dept=new Dept();
dept.setDeptName("市场部");
dept.setDeptAddress("深圳");
int i=deptDaoImpl.insert(dept);
System.out.println("受影响行数:"+i);
} }

2.基本的CRUD操作

2.1         准备工作(继续使用前面的库表和代码)

2.2         别名与自定义别名

2.2.1  内置别名

对常用的 java 类型,已经内置了一些别名支持。这些别名都是不区分大小写的。(详细参看用户手机)

2.2.2  自定义别名

在myBatis的主配置文件给cn.it.entity.Dept类创建别名Dept,后继的DeptMapper.xml配置文件中可以使用别名

<!-- 通过别名简化对类的使用 -->
<typeAliases>
<typeAlias type="cn.it.entity.Dept" alias="Dept" />
</typeAliases>

2.3  MyBatisUtil工具类

public class MyBatisUtil {

    private static final ThreadLocal<SqlSession> threadLocal = new ThreadLocal<SqlSession>();
private static SqlSessionFactory sessionFactory; private static String CONFIG_FILE_LOCATION = "myBatis-config.xml"; static {
try {
buildSessionFactory();
} catch (Exception e) {
System.err.println("%%%% Error Creating SessionFactory %%%%");
e.printStackTrace();
}
}
private MyBatisUtil() {
} /**
* Returns the ThreadLocal Session instance. Lazy initialize
* the <code>SessionFactory</code> if needed.
*
* @return Session
* @throws Exception
*/
public static SqlSession getSession() throws Exception {
SqlSession session = (SqlSession) threadLocal.get(); if (session == null) {
if (sessionFactory == null) {
buildSessionFactory();
}
session = (sessionFactory != null) ? sessionFactory.openSession()
: null;
threadLocal.set(session);
} return session;
} /**
* build session factory
*
*/
public static void buildSessionFactory() {
Reader reader=null;
try {
reader=Resources.getResourceAsReader(CONFIG_FILE_LOCATION);
sessionFactory = new SqlSessionFactoryBuilder().build(reader);
} catch (Exception e) {
System.err.println("%%%% Error Creating SessionFactory %%%%");
e.printStackTrace();
}finally{
try {
reader.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} /**
* Close the single session instance.
*
*/
public static void closeSession(){
SqlSession session = (SqlSession) threadLocal.get();
threadLocal.set(null); if (session != null) {
session.close();
}
} /**
* return session factory
*
*/
public static SqlSessionFactory getSessionFactory() {
return sessionFactory;
}
}

2.3         CRUD操作

2.3.1  新增操作

配置文件DeptMapper.xml使用别名, DeptDaoImpl.java新增方法使用工具类。

修改配置文件DeptMapper.xml(使用别名):

<!--parameterType="Dept"不写时,也能自动根据代码传递的参数Dept自动匹配 内容-->
<insert id="insert" parameterType="Dept">
insert into dept(dept_name) values(#{deptName});
</insert>

修改DeptDaoImpl.java新增方法(使用MyBatisUtil.java工具类):

/**
* @param dept 部门信息
* @return 保存信息后受影响的行数
*/
public int saveDept(Dept dept) {
int i = 0;
try {
session = MyBatisUtil.getSession();
i = session.insert("cn.it.entity.DeptMapper.insertDept", dept);
session.commit();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
session.rollback();
} finally {
try {
MyBatisUtil.closeSession();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} return i;
}

2.3.2  修改操作

修改配置文件deptMapper.xml,添加

<update id="update" parameterType="Dept">
update dept set dept_name=#{deptName} ,dept_address=#{deptAddress} where dept_id=#{deptId}
</update>

修改DeptDaoImpl.java,添加update方法:

public int  update(Dept dept){
SqlSession session = null;
int i=0; try {
session=MyBatisUtil.getSession();
//方法的第一个参数为DeptMapper.xml文件的命名空间+id
i=session.update("cn.it.entity.DeptMapper.update",dept);
System.out.println("受影响行数:"+i);
session.commit();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
session.rollback(); }finally{
MyBatisUtil.closeSession();
}
return i;
}

2.3.3  删除操作

修改配置文件deptMapper.xml,添加

<delete id="delete" parameterType="Dept">
delete from dept where dept_id=#{deptId}
</delete>

修改DeptDaoImpl.java,添加delete方法:

public int delete(Dept dept){
int i = 0;
try {
session=MyBatisUtil.getSession();
//方法的第一个参数为DeptMapper.xml文件的命名空间+id
i=session.delete("cn.it.entity.DeptMapper.delete",dept);
//System.out.println("受影响行数:"+i);
session.commit();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
session.rollback(); }finally{
MyBatisUtil.closeSession();
}
return i;
}

2.3.4  查询操作(返回单条记录)

配置deptMapper.xml文件的resultMap元素及SQL查询语句

<!-- 表字段和实体属性命名一致时可以不配置 -->
<resultMap id="deptResultMap" type="Dept">
<id property="deptId" column="dept_id"/>
<result property="deptName" column="dept_name"/>
<result property="deptAddress" column="dept_address"/>
</resultMap>
<!—省略其它的配置信息 -->
<!—返回单条记录,表字段和对应实体属性命名一致时可以不使用resultMap属性配置,直接使用resultType="返回的全类名或别名",建议使用前者;查询结果为所有字段时,也可以用*表示 -->
<select id="selectOne" parameterType="int" resultMap="deptResultMap" >
select dept_id, dept_name from dept where dept_id=#{deptId}
</select>

修改DeptDaoImpl.java,添加selectOne方法:

public Dept selectOne(int deptId){
Dept dept=null;
try {
session=MyBatisUtil.getSession();
dept=(Dept)session.selectOne("cn.it.entity.DeptMapper.selectOne",deptId);
System.out.println("dept:"+dept);
} catch (Exception e) {
e.printStackTrace();
}finally{
MyBatisUtil.closeSession();
}
return dept;
}

2.3.5  查询操作(返回多条记录)

修改配置文件deptMapper.xml,添加

<!-- 返回多条记录,返回结果配置的不是集合类型,而是集合元素的类型;参数也可以通过Map等方式封装  -->
<select id="selectList" parameterType="Map" resultMap="deptResultMap">
select * from dept where dept_name like #{deptName}
</select>

修改DeptDaoImpl.java,添加selectList方法:

public List<Dept> selectList(Map map){
List<Dept> depts=null;
try {
session=MyBatisUtil.getSession();
depts=session.selectList("cn.it.entity.DeptMapper.selectList",map);
} catch (Exception e) {
e.printStackTrace();
}finally{
MyBatisUtil.closeSession();
}
return depts;
}

测试类代码:

@Test
public void testSelectList() {
Map map=new HashMap();
map.put("deptName", "%研%");
List<Dept> depts=deptDaoImpl.selectList(map);
for(Dept dept:depts){
System.out.println("dept:"+dept);
}
}

3.动态SQL操作

3.1    准备工作

创建表及库,实体类,配置文件(参考上章节内容),以下为建表和库的SQL:

drop database if exists mybatis;
create database mybatis CHARACTER SET UTF8;
use mybatis; create table dept(
dept_id int primary key auto_increment,
dept_name varchar(50),
dept_address varchar(50)
); insert into dept(dept_name,dept_address) values('研发部一部','广州');
insert into dept(dept_name,dept_address) values('研发部二部','广州');
insert into dept(dept_name,dept_address) values('研发部三部','深圳');
select * from dept;

3.2  IF语句

修改配置文件deptMapper.xml,添加

<!-- 动态IF条件 -->
<select id="selectListUseIf" parameterType="Dept" resultMap="deptResultMap">
select * from dept where 1=1
<if test="deptId!=null">
and dept_id=#{deptId}
</if>
<if test="deptName!=null">
and dept_name=#{deptName}
</if>
<if test="deptAddress!=null">
and dept_address=#{deptAddress}
</if>
</select>

修改DeptDaoImpl.java,添加selectListUseIf方法:

//根据参数使用配置文件的IF语句自动填充查询的过滤条件
public List<Dept> selectListUseIf(Dept dept){
List<Dept> depts=null;
try {
session=MyBatisUtil.getSession();
depts=session.selectList("cn.it.entity.DeptMapper.selectListUseIf",dept);
} catch (Exception e) {
e.printStackTrace();
}finally{
MyBatisUtil.closeSession();
}
return depts;
}

3.3  WHERE语句

修改配置文件deptMapper.xml,添加

<!-- 动态Where条件 ,一般也需要与if结合使用,与纯if比较,省略了where 1=1-->
<select id="selectListUseWhere" parameterType="Dept" resultMap="deptResultMap">
select * from dept
<where>
<if test="deptId!=null">
and dept_id=#{deptId}
</if>
<if test="deptName!=null">
and dept_name=#{deptName}
</if>
<if test="deptAddress!=null">
and dept_address=#{deptAddress}
</if>
</where>
</select>

3.4  choose(when,otherwise)语句

修改配置文件deptMapper.xml,添加

<!-- 动态choose条件 ,如下配置,可以完成没有选择条件时,查找不出任何数据 -->
<select id="selectListUseChoose" parameterType="Dept" resultMap="deptResultMap">
select * from dept where 1=1
<choose>
<when test="deptId!=null">and dept_id=#{deptId}</when>
<when test="deptName!=null">and dept_name=#{deptName}</when>
<when test="deptAddress!=null">and dept_address=#{deptAddress}</when>
<otherwise>and !1 = 1</otherwise>
</choose>
</select>

3.5  SET语句

修改配置文件deptMapper.xml,添加

<!--动态set语句可以用来更新数据 -->
<update id="updateUseSet" parameterType="Dept">
update dept
<set>
<if test="deptName!=null">dept_name=#{deptName},</if>
<if test="deptAddress!=null">dept_address=#{deptAddress},</if>
</set>
where dept_id=#{deptId}
</update>

3.6  ForEach语句

修改配置文件deptMapper.xml,添加

< <!-- 定义根据多个部门ID查询部门相关部门信息的SQL语句 ,resultMap的值是指集合里元素的类型,parameterType不用指定 -->
<select id="selectListUseForeach" parameterType="Integer[]" resultMap="deptResultMap">
select * from dept where dept_id in
<!-- collection="array或list",array用来对应参数为数组,list对应参数为 集合 -->
<foreach collection="array" item="deptId" open="(" separator="," close=")">
#{deptId}
</foreach>
</select>

3.7  include语句

修改配置文件deptMapper.xml,添加

<!-- 使用include语句动态插入表的字段及对应的值 -->
<sql id="key">
<!--suffixOverrides="," 可以忽略最后“,”号 -->
<trim suffixOverrides=","> <if test="deptName!=null">
dept_name,
</if>
<if test="deptAddress!=null">
dept_address,
</if>
</trim>
</sql>
<sql id="value">
<trim suffixOverrides="," >
<if test="deptName!=null">
#{deptName},
</if>
<if test="deptAddress!=null">
#{deptAddress},
</if>
</trim>
</sql> <insert id="insertUseInclude" parameterType="Dept">
insert into dept(
<include refid="key" />
) values(
<include refid="value"/>
)
</insert>