mybatis的jar包
工程结构
1.mybatis的基本构成:
SqlSessionFactoryBuilder(构造器):根据配置信息或者代码来生成SqlSessionFactory
SqlSessionFactory(工厂接口):依靠工厂来生成SqlSession
SqlSession(会话):是一个既可以发送SQL去执行并返回结果,也可以获取Mapper的接口
SQL Mapper:有一个Java接口和xml文件或者注解构成,需要给出对应的SQL和映射规则。负责发送sql去执行,并返回结果
注意:使用xml配置文件是为了避免硬编码(hard code)
xml配置文件读取后的信息主要是保存在Configuration(org.apache.ibatis.session.Configuration)该对象中
注意:mybatis提供了两个SqlSessionFactory的实现类:DefaultSQLSessionFactory(主要是使用这个)和SqlSessionManager
2.xml配置
DataSource(获取数据库连接实例的数据源)
TransactionManager(决定事务范围和控制方式的事务管理器)
SQL Mapper(映射器)
<?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>
<typeAliases><!-- 设置pojo对象的别名 -->
<typeAlias alias="Emp" type="com.unicorn.mybatishw.pojo.Emp"/>
</typeAliases>
<!--定义数据库的信息,默认使用development数据库构建环境-->
<environments default="development">
<!-- 采用JDBC事务管理 -->
<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/test?characterEncoding=utf8"/>
<property name="username" value="Ben"/>
<property name="password" value="220401"/>
</dataSource>
</environment>
</environments>2
<!-- 定义映射器 -->
<mappers>
<mapper resource="com/unicorn/mybatishw/dao/EmpDaoMapper.xml"/>
</mappers>
</configuration>
MybatisUtils
package com.unicorn.mybatishw.utils;
import java.io.Reader;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class MyBatisUtil {
private MyBatisUtil(){
}
private static final String RESOURCE = "mybatis-config.xml";
private static SqlSessionFactory sqlSessionFactory = null;
private static ThreadLocal<SqlSession> threadLocal = new ThreadLocal<SqlSession>();
static {
Reader reader = null;
try {
reader = Resources.getResourceAsReader(RESOURCE);
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
sqlSessionFactory = builder.build(reader);
} catch (Exception e1) {
throw new ExceptionInInitializerError("初始化MyBatis错误,请检查配置文件或数据库");
}
}
public static SqlSessionFactory getSqlSessionFactory(){
return sqlSessionFactory;
}
public static SqlSession getSession(){
//sessionTL的get()方法根据当前线程返回其对应的线程内部变量,
//也就是我们需要的Session,多线程情况下共享数据库链接是不安全的。
//ThreadLocal保证了每个线程都有自己的Session。
SqlSession session = threadLocal.get();
// 如果session为null,则打开一个新的session
if (session == null){
session = (sqlSessionFactory !=null) ?sqlSessionFactory.openSession():null;
threadLocal.set(session); // 5
}
return session;
}
public static void closeSession(){
SqlSession session = (SqlSession) threadLocal.get(); // 2
threadLocal.set(null);
if (session !=null){
session.close();
}
}
}
读取xml配置文件,生成SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream is = Resource.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = null;
SqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
流程:
①输入流(InputStream)读取配置文件(Resource.getResourceAsStream(“”))->
②SqlSessionFactoryBuilder通过InputStream创建SqlSessionFactory->
③SqlSessionFactory
其次还能通过Java代码实现配置
//创建数据库连接池
PooledDataSource dataSource = new PooledDataSource();
dataSource.setDriver("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/数据库名称?characterEncoding=utf8");
dataSource.setUsername("数据库管理员名称");
dataSource.setPassword("xxxx");
//构建数据库事务方式
TransactionFactory transctionFactory = new JdbcTransctionFactory();
//创建数据库的运行环境
Environment environment = newEnvironment("development", transctionFactory, dataSource);
//构建Configuration对象
Configuration configuration = new Configuration(environment);
//注册别名alias
configuration.getTypeAlisRegistry().registerAlias("Emp", Emp.class);
//加入映射器
configuration.addMapper(EmpMapper.class);
//使用SqlSessionFactoryBulider构建SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);
SqlSession属于数据库资源,在一次使用完之后应该及时关闭(即在finally中关闭),避免占用数据库资源
伪代码
SqlSession sqlSession = null;
try{
sqlSession = sqlSessionFactory.openSession();//getCurrentSession?
//some code ...
sqlSession.commit();//提交事务
} catch(Exception ex){
System.err.println("");
sqlsession.rollback();//事务回滚
} finally {
if(null != sqlSession)
sqlSession.close();
}
3.实体对象的映射配置
Emp.class
package com.unicorn.mybatishw.pojo;
import java.io.Serializable;
import java.sql.Date;
public class Emp implements Serializable {
/**
* 实现序列化接口
*/
private static final long serialVersionUID = 1L;
/**
* 雇员的数据成员
*/
// 雇员的工号
private Integer empno;
// 雇员姓名
private String empName;
// 雇员的工作类型
private String job;
// 雇员的薪水
private Double salary;
// 雇员的奖金
private Double comm;
// 雇员的入职事件
private Date hireDate;
// 雇员的经理的工号
private Integer mgr;
// 雇员的部门
private String deptno;
public Emp() {
// TODO Auto-generated constructor stub
}
// settrt and getter
public Integer getEmpno() {
return empno;
}
public void setEmpno(Integer empno) {
this.empno = empno;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
public Double getSalary() {
return salary;
}
public void setSalary(Double salary) {
this.salary = salary;
}
public Double getComm() {
return comm;
}
public void setComm(Double comm) {
this.comm = comm;
}
public Date getHireDate() {
return hireDate;
}
public void setHireDate(Date hireDate) {
this.hireDate = hireDate;
}
public Integer getMgr() {
return mgr;
}
public void setMgr(Integer mgr) {
this.mgr = mgr;
}
public String getDeptno() {
return deptno;
}
public void setDeptno(String deptno) {
this.deptno = deptno;
}
public static long getSerialversionuid() {
return serialVersionUID;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return this.getEmpName()+":"+this.getJob()+"<--> salary:"+this.getSalary()+
" comm:"+ this.getComm();
}
}
IEmpDao.interface
package com.unicorn.mybatishw.dao;
import java.util.List;
import com.unicorn.mybatishw.pojo.Emp;
public interface IEmpDao {
// 添加新的雇员
int addNewEmp(Emp newEmp);
// 删除一个雇员
boolean deleteEmp(Emp emp);
// 修改雇员信息
boolean updateEmpByEmpno(Emp emp);
// 多条件合并查找雇员
List<Emp> queryEmpBySomeCondition(Emp emp);
// 查询所有雇员
List<Emp> queryEmps();
}
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.unicorn.mybatishw.dao.IEmpDao">
<!-- 利用别名代替 -->
<resultMap type="Emp" id="empResultMap">
<id property="empno" column="empno" /><!-- id绑定主键 -->
<result property="empName" column="ename" />
<result property="hireDate" column="hiredate" />
<result property="job" column="job" />
<result property="comm" column="comm" />
<result property="salary" column="sal" />
<result property="deptno" column="deptno" /> <!-- pojo 与数据库表column名设计一致可以不用使用resultmap -->
</resultMap>
<!-- <select resultType="int" id="countAll">
这里的SQL结尾不能加分号,否则报"ORA-00911错误"
SELECT count(*) FROM emp
</select>
<select resultType="Emp" id="selectOneEmp" resultMap="empResultMap">
SELECT *
FROM
emp
WHERE
empno=1002
</select>
<delete id="deleteEmpByEmpno" parameterType="int">
DELETE FROM
emp
WHERE
empno= #{empno}
</delete>
<update id="updateEmpByEmpno" parameterType="Emp">
UPDATE
emp e
SET
e.ename=#{empName}, e.job=#{job}, e.sal=#{salary}, e.comm=#{comm}
WHERE
e.empno=#{empno}
</update>
<select id="dynamicQueryEmp" parameterType="Emp" resultType="Emp" resultMap="empResultMap">
SELECT e.* FROM
emp e
<where>
<if test="mgr != null">
and e.mgr=#{mgr}
</if>
<if test="empName != null">
and e.ename like '%${empName}%'
</if>
</where>
</select>
<select resultType="Emp" id="queryEmpByEmpNo" parameterType="int" resultMap="empResultMap">
SELECT *
FROM
emp
WHERE
empno= #{empno}
</select>
<select resultType="Emp" id="queryAllEmp" resultMap="empResultMap">
SELECT *
FROM
emp
</select>
<select resultType="Emp" id="queryEmpByDeptno" resultMap="empResultMap">
SELECT e.*
FROM
emp e
WHERE
e.deptno=#{deptno}
</select>
<select resultType="Emp" id="queryEmpByDeptnoLike" parameterType="String" resultMap="empResultMap">
SELECT e.*
FROM
emp e
WHERE
e.deptno like concat('%', #{deptno})利用字符拼接
</select>
<insert id="addNewEmp" parameterType="Emp" useGeneratedKeys="true" keyProperty="empno">useGeneratedKeys="true" keyProperty="empno"可以使对像直接获取自增的值
INSERT INTO emp
(empno, ename, job, sal, comm, mgr, deptno)
VALUES
(#{empno}, #{empName}, #{job}, #{salary}, #{comm}, #{mgr}, #{deptno})
</insert> -->
<insert id="addNewEmp" parameterType="Emp" useGeneratedKeys="true" keyProperty="empno">
INSERT INTO emp
(empno, ename, job, sal, comm, mgr, deptno, hiredate)
VALUES
(#{empno}, #{empName}, #{job}, #{salary}, #{comm}, #{mgr}, #{deptno}, #{hireDate})
</insert>
<select id="queryEmpBySomeCondition" parameterType="Emp" resultType="Emp" resultMap="empResultMap">
SELECT e.* FROM
emp e
<where>
<if test="empno != null">
and e.empno=#{empno}
</if>
<if test="empName != null">
and e.ename like '%${empName}%'
</if>
<if test="deptno != null">
and e.deptno like '%${deptno}%'
</if>
<if test="job != null">
and e.job like '%${job}%'
</if>
<if test="mgr != null">
and e.mgr like '%${mgr}%'
</if>
<if test="salary != null">
and e.sal=#{salary}
</if>
</where>
</select>
<select resultType="Emp" id="queryEmps">
SELECT * FROM emp
</select>
</mapper>
参考:注解配置
public interface EmpMapper{
@Select(value="select id, job, salary, empName from emp where id=#{id}");//相当于<select>
//</select>
public Emp getEmpById(Long id);
}
最好使用类对象的mapper接口(interface)进行开发,个人的经验来看注解的方式来写mybatis的sql难以做到对数据判断,如下面这条select
<select id="queryEmpBySomeCondition" parameterType="Emp" resultType="Emp" resultMap="empResultMap">
SELECT e.* FROM
emp e
<where>
<if test="empno != null">
and e.empno=#{empno}
</if>
<if test="empName != null">
and e.ename like '%${empName}%'
</if>
<if test="deptno != null">
and e.deptno like '%${deptno}%'
</if>
<if test="job != null">
and e.job like '%${job}%'
</if>
<if test="mgr != null">
and e.mgr like '%${mgr}%'
</if>
<if test="salary != null">
and e.sal=#{salary}
</if>
</where>
</select>
使用xml的mapper是很容易做到的,而使用注解就比较麻烦
相应的project链接
环境:eclipse Java Oxygen(June 2017)
转载请注明出处,谢谢!
感谢杨开振先生所著的《深入浅出Mybatis技术原理与实战》,笔者博客的内容一部分是自己实战中的经验,另一部分是学习这本书籍内容的总结。