MyBatis学习笔记(一)
mybatis介绍,快速入门
个人笔记,如有错误,恳请批评指正。
1. Mybatis介绍
MyBatis 世界上流行最广泛的基于SQL语句的ORM框架,由Clinton Begin 在2002 年创建,其后,捐献给了Apache基金会,成立了iBatis 项目。MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。
2. 与Hibernate比较
a. 学习成本:MyBatis简单易学(特别是有SQL语法基础的人),较接近JDBC
b. 程序灵活性:MyBatis直接使用SQL,灵活性高
c. 程序执行效律:MyBatis效律高
d. 可移植性:hibernate较好(与数据库关联在配置中完成,HQL语句与数据库无关)
mybatis提供一种“半自动化”的ORM实现。
这里的“半自动化”,是相对Hibernate等提供了全面的数据库封装机制的“全自动化”ORM实现而言,“全自动”ORM实现了POJO和数据库表之间的映射,以及SQL的自动生成和执行。而mybatis的着力点,则在于POJO与SQL之间的映射关系。
3. 适用场所
MyBatis是一个灵活的DAO层解决方案,满足较高的性能要求,可以在很多场合使用,但一般以下场合不建议使用:
a. 需要支持多种数据库或数据库有移植要求
b. 完全动态sql,例如:字段要动态生成
c. 使用的不是关系数据库
4. 开发步骤
- 新建JAVA项目或WEB项目
- 部署jar包(包括数据库驱动包):使用MyBatis需要先下载jar包:下载地址http://code.google.com/p/mybatis
- 编写主配置文件 myBatis-config.xml
- 创建数据库及表(如已创建,可省略)newfile.sql
- 创建实体类及SQL映射文件 XXXMapper.xml
- 编写数据库接口及实现
- 编写测试类及测试
5. 开发示例
- 新建项目
- 导包
导入mybatis和数据库驱动包、日志包(配置日志配置文件)。 - 创建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&characterEncoding=UTF-8,如下 -->
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=UTF-8" />
<property name="username" value="root" />
<property name="password" value="root" />
</dataSource>
</environment>
</environments>
</configuration>
- 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;
- 创建实体类:Dept.java
- 创建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.itcast.entity.DeptMapper">
<!-- 一般在查询时使用-->
<resultMap type="cn.itcast.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.itcast.entity.Dept">
insert into dept(dept_name,dept_address) values(#{deptName},#{deptAddress});
</insert>
</mapper>
sql映射文件建立了POJO与SQL之间的依赖关系。
此时需要更新myBatis-config.xml中对sql映射配置的应用。
- 修改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/itcast/entity/DeptMapper.xml" />
</mappers>
</configuration>
- 编写数据库操作
包括操作接口及实现,接口略,实现类为:DeptDaoImpl.java
public class DeptDaoImpl {
private SqlSession session = null;
/*
*1.读取配置文件信息
*2.构建session工厂
*3.创建session
*4.开启事务
*5.处理数据
*6.提交/回滚数据
*7.关闭session
*/
@Deprecated
public int save(Dept dept){
int i = 0;
String path = "mybatis-config.xml";
SqlSession session = null;
Reader reader = null;
try {
reader = Resources.getResourceAsReader(path);
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);
session = sessionFactory.openSession();
//参数1:定义的sql 参数2:sql的值
// SQL映射文件定义的命名空间+SQL语句的ID定位SQL语句
i = session.insert("cn.ustb.entity.DeptMapper.insertDept", dept);
session.commit();
} catch (Exception e) {
e.printStackTrace();
session.rollback();
}
finally{
if(reader != null){
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(session != null){
session.close();
}
}
return i;
}
- 编写测试类
需要导入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);
}
}
6. 基本的CRUD操作
- 准备工作(继续使用前面的库表和代码)
- 别名与自定义别名
- 内置别名
对常用的 java 类型,已经内置了一些别名支持。这些别名都是不区分大小写的。(详细参看用户手册)
自定义别名
在myBatis的主配置文件给cn.itcast.entity.Dept类创建别名Dept,后继的DeptMapper.xml配置文件中可以使用别名
<!-- 通过别名简化对类的使用 -->
<typeAliases>
<typeAlias type="cn.ustb.entity.Dept" alias="Dept" />
</typeAliases>
MyBatisUtil工具类
封装了获取及关闭session的操作,并保证在线程池中始终只有一份session,节省了资源。
public class MybatisSessionFactory {
private static final ThreadLocal<SqlSession> threadLocal = new ThreadLocal<SqlSession>();
private static SqlSessionFactory sqlSessionFactory = null;
private static String CONFIG_FILE_LOCATION = "myBatis-config.xml";
private static String configFile = CONFIG_FILE_LOCATION;
static{
buildSessionFactory();
}
public static SqlSession getSession() throws Exception{
SqlSession session = threadLocal.get();
if(session == null){
if(sqlSessionFactory == null){
buildSessionFactory();
}
session = (sqlSessionFactory!=null)? sqlSessionFactory.openSession():null;
threadLocal.set(session);
}
return session;
}
public static void closeSession(){
SqlSession session = threadLocal.get();
threadLocal.set(null);
if(session != null ){
session.close();
System.out.println("***Success Session Closing***");
}
}
public static void buildSessionFactory(){
Reader reader = null;
try {
reader = Resources.getResourceAsReader(CONFIG_FILE_LOCATION);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
} catch (Exception e) {
e.printStackTrace();
System.out.println("%%%%Create sessionFactory error%%%%");
}finally{
if(reader!=null){
try {
reader.close();
System.out.println("***Success reader Closing***");
} catch (Exception e) {
System.out.println("%%%% Closing sessionFactory error %%%%");
e.printStackTrace();
}
}
}
}
}
新增操作:INSERT
修改DeptMapper.xml配置insert语句(使用之前配置好的别名)
<!--parameterType="Dept"不写时,也能自动根据代码传递的参数Dept自动匹配 内容-->
<insert id="insert" parameterType="Dept">
insert into dept(dept_name) values(#{deptName});
</insert>
修改DeptDaoImpl.java新增方法(使用MyBatisUtil.java工具类):
public int save2(Dept dept){
int i = 0;
SqlSession session = null;
try {
session = MybatisSessionFactory.getSession();
//参数1:定义的sql 参数2:sql的值
i = session.insert("cn.ustb.entity.DeptMapper.insertDept", dept);
session.commit();
} catch (Exception e) {
e.printStackTrace();
session.rollback();
}
finally{
MybatisSessionFactory.closeSession();
}
return i;
}
删除操作:DELETE
修改配置文件deptMapper.xml,添加
<delete id="delete" parameterType="Dept">
delete from dept where dept_id=#{deptId}
</delete>
修改DeptDaoImpl.java,添加delete方法:
public boolean delete(Integer id){
boolean state = false;
try {
session = MybatisSessionFactory.getSession();
int i = session.delete("cn.ustb.entity.DeptMapper.deleteDept",id);
session.commit();
if(i!=0)state = true;
} catch (Exception e) {
e.printStackTrace();
session.rollback();
state = false;
}finally{
MybatisSessionFactory.closeSession();
}
return state;
}
修改操作:UPDATE
修改配置文件deptMapper.xml,添加update语句。传入的值用spel表达式#{}获取
<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){
int i = 0;
try {
session = MybatisSessionFactory.getSession();
i = session.update("cn.ustb.entity.DeptMapper.updateDept", dept);
session.commit();//necessary
} catch (Exception e) {
e.printStackTrace();
session.rollback();
}finally{
MybatisSessionFactory.closeSession();
}
return i;
}
查询操作:SELECT
- 查询操作(返回单条记录)
配置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="selectDept" parameterType="integer" resultMap="deptResultMap">
<!-- 指定返回的类型,按照Map定义的规则封装对象 -->
select dept_id,dept_name,dept_address from dept where dept_id = #{deptId}
</select>
修改DeptDaoImpl.java,添加selectOne方法:
public Dept selectOne(Integer id){
Dept dept = null;
try {
session = MybatisSessionFactory.getSession();
dept = session.selectOne("cn.ustb.entity.DeptMapper.selectDept",id);
session.commit();
} catch (Exception e) {
e.printStackTrace();
session.rollback();
}finally{
MybatisSessionFactory.closeSession();
}
return dept;
}
- 查询操作(返回多条记录)
修改配置文件deptMapper.xml,添加
<!-- 返回多条记录,返回结果配置的不是集合类型,而是集合元素的类型;参数也可以通过Map等方式封装 -->
<!-- 多个查询 -->
<!-- 如果返回的是list,resultMap指定的值是list集合里面的类型 -->
<select id="selectMultiDept" parameterType="String" resultMap="deptResultMap">
select * from dept where dept_address = #{deptAddress}
</select>
<!-- 参数类型用map的多个查询 -->
<select id="selectMultiDeptUseMapParamter" parameterType="Map" resultMap="deptResultMap">
select * from dept where dept_address like #{deptAddress}
</select>
修改DeptDaoImpl.java,添加selectList方法:
public List<Dept> selectMulti(String deptAddress){
List<Dept> list = null;
try {
session = MybatisSessionFactory.getSession();
list = session.selectList("cn.ustb.entity.DeptMapper.selectMultiDept", deptAddress);
session.commit();
} catch (Exception e) {
e.printStackTrace();
session.rollback();
}
return list;
}
/*
* 模糊查询在sql中添加like,在传入条件中添加%
*/
public List<Dept> selectMultiUserMapParameter(Map deptAddresses){
List<Dept> list = null;
try {
session = MybatisSessionFactory.getSession();
list = session.selectList("cn.ustb.entity.DeptMapper.selectMultiDeptUseMapParamter", deptAddresses);
session.commit();
} catch (Exception e) {
e.printStackTrace();
session.rollback();
}
return list;
}
测试类代码:
@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);
}
}