Mybatis
-
Mybatis 介绍
MyBatis是支持普通 SQL 查询,存储过程和高级映射的优秀持久 层框架。MyBatis 消除了几乎所有的 JDBC 代码和参数的手工设置以 及对结果集的检索封装。MyBatis 可以使用简单的 XML 或注解用于 配置和原始映射,将接口和 Java 的 POJO(Plain Old Java Objects,普 通的 Java 对象)映射成数据库中的记录.
-
常见的ORM框架
JDBC‐dbUtils‐ MyBatis‐ Hibernate
-
mybatis 快速入门
maven依赖
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.36</version>
</dependency>
建库建表
CREATE TABLE emp
(
empno INT(10) UNSIGNED PRIMARY KEY NOT NULL AUTO_INCREMENT,
ename VARCHAR(15),
job VARCHAR(10),
mgr INT(10) UNSIGNED,
hiredate DATE,
sal DECIMAL(7,2),
comm DECIMAL(7,2),
deptno INT(10) UNSIGNED,
hiredateb DATETIME,
mgrb INT(11),
phone VARCHAR(255),
CONSTRAINT emp_ibfk_1 FOREIGN KEY (deptno) REFERENCES dept (deptno)
);
CREATE INDEX deptno ON emp (deptno);
INSERT INTO scott.emp (ename, job, mgr, hiredate, sal, comm, deptno, hiredateb, mgrb, phone) VALUES ('JONES', 'MANAGER', 7839, '1981-04-02', 2975.00, null, 20, null, null, null);
INSERT INTO scott.emp (ename, job, mgr, hiredate, sal, comm, deptno, hiredateb, mgrb, phone) VALUES ('MARTIN', 'SALESMAN', 7698, '1981-09-28', 1250.00, 1400.00, 30, null, null, null);
INSERT INTO scott.emp (ename, job, mgr, hiredate, sal, comm, deptno, hiredateb, mgrb, phone) VALUES ('BLAKE', 'MANAGER', 7839, '1981-05-01', 2850.00, null, 30, null, null, null);
INSERT INTO scott.emp (ename, job, mgr, hiredate, sal, comm, deptno, hiredateb, mgrb, phone) VALUES ('CLARK', 'MANAGER', 7839, '1981-06-09', 2450.00, null, 10, null, null, null);
INSERT INTO scott.emp (ename, job, mgr, hiredate, sal, comm, deptno, hiredateb, mgrb, phone) VALUES ('SCOTT', 'ANALYST', 7566, '1987-07-13', 3000.00, null, 20, null, null, null);
INSERT INTO scott.emp (ename, job, mgr, hiredate, sal, comm, deptno, hiredateb, mgrb, phone) VALUES ('KING', 'PRESIDENT', null, '1981-11-17', 5000.00, null, 10, null, null, null);
INSERT INTO scott.emp (ename, job, mgr, hiredate, sal, comm, deptno, hiredateb, mgrb, phone) VALUES ('TURNER', 'SALESMAN', 7698, '1981-09-08', 1500.00, 0.00, 30, null, null, null);
INSERT INTO scott.emp (ename, job, mgr, hiredate, sal, comm, deptno, hiredateb, mgrb, phone) VALUES ('ADAMS', 'CLERK', 7788, '1987-07-13', 1100.00, null, 20, null, null, null);
INSERT INTO scott.emp (ename, job, mgr, hiredate, sal, comm, deptno, hiredateb, mgrb, phone) VALUES ('JAMES', 'CLERK', 7698, '1981-12-03', 950.00, null, 30, null, null, null);
INSERT INTO scott.emp (ename, job, mgr, hiredate, sal, comm, deptno, hiredateb, mgrb, phone) VALUES ('FORD', 'ANALYST', 7566, '1981-12-03', 3000.00, null, 20, null, null, null);
添加配置文件
<?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>
<properties resource="jdbc.properties"></properties>
<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:///scott"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="*/*/bean/EmpMapper.xml"></mapper>
</mappers>
</configuration>
创建实体类
public class Emp implements Serializable {
private Integer empno;
private String ename;
private String job;
private Double sal;
private Dept dept;
}
创建mapper文件
<?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="*.*.EmpMapper">
</mapper>
注册mapper文件
<mappers>
<mapper resource="*/*/bean/EmpMapper.xml"></mapper>
</mappers>
执行定义的select语句
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
List<Emp> emps = sqlSession.selectList("cn.bdqn.bean.EmpMapper.selectEmp");
for (Emp emp : emps) {
System.out.println(emp);
}
操作 users 表的 CRUD
XML的实现
注解的实现
几个可以优化的地方
连接数据库的配置单独放在一个 properties 文件中
driver=com.mysql.jdbc.Driver
url=jdbc:mysql:///scott
username=root
password=root
<properties resource="jdbc.properties"></properties>
可以在 src 下加入 log4j 的配置文件,打印日志信息
log4j.rootLogger=DEBUG, Console
#Console
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%d [%t] %‐5p [%c] ‐ %m%n
log4j.logger.java.sql.ResultSet=INFO
log4j.logger.org.apache=INFO
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
<settings>
<setting name="logImpl" value="LOG4J" />
</settings>
SqlSessionFacotryUtils
private static final ThreadLocal<SqlSession> threadLocal = new ThreadLocal<SqlSession>();
private static SqlSessionFactory sessionFactory;
static String CONFIG_FILE_LOCATION = "mybatis-config.xml";
static InputStream inputStream;
private static Properties properties;
static {
try {
properties= new Properties();
properties.load(MyBatisSessionFactory.class.getClassLoader().getResourceAsStream("jdbc.properties"));
inputStream = Resources.getResourceAsStream(CONFIG_FILE_LOCATION);
sessionFactory = new SqlSessionFactoryBuilder().build(inputStream,properties);
} catch (Exception e) {
System.err.println("%%%% Error Creating SessionFactory %%%%");
e.printStackTrace();
}
}
private MyBatisSessionFactory() {
}
public static SqlSession getSession() {
System.out.println("1111111111111");
SqlSession session = (SqlSession) threadLocal.get();
if (session == null) {
if (sessionFactory == null) {
rebuildSessionFactory();
}
session = (sessionFactory != null) ? sessionFactory.openSession()
: null;
threadLocal.set(session);
}
return session;
}
public static void rebuildSessionFactory() {
try {
inputStream = Resources.getResourceAsStream(CONFIG_FILE_LOCATION);
sessionFactory = new SqlSessionFactoryBuilder().build(inputStream,properties);
} catch (Exception e) {
System.err.println("%%%% Error Creating SessionFactory %%%%");
e.printStackTrace();
}
}
public static void closeSession() {
SqlSession session = (SqlSession) threadLocal.get();
threadLocal.set(null);
if (session != null) {
session.close();
}
}
public static SqlSessionFactory getSessionFactory() {
return sessionFactory;
}
public static void setConfigFile(String configFile) {
MyBatisSessionFactory.CONFIG_FILE_LOCATION = configFile;
sessionFactory = null;
}
解决字段名与实体类属性名不相同的冲突
准备表和数据
定义实体类
查询
as
ResultMap
实现关联表查询
需求
员工和员工详细信息
一对一
Association 用于一对一的关联查询
Property :对象属性的名称
Javatype:对象属性的类型
Column:所对应的外键字段名称
Select:使用另一个查询封装结果
嵌套结果
嵌套查询
一对多关联
Collection : 一对多关联查询
ofType:指定集合中元素对象的类型
嵌套结果
嵌套查询
动态 SQL 与模糊查询
If
Choose(when otherwise)
Trim(where,set)
Foreach
调用存储过程
Mybatis 缓存
一级缓存: 基于 PerpetualCache 的 HashMap 本地缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该 Session 中的所有 Cache 就将清空。
二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap 存储,不同在于 其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache
对于缓存数据更新机制,当某一个作用域(一级缓存 Session/二级缓存 Namespaces)的进行了 C/U/D 操作后,默认该作用域下所有 select 中的缓存将被 clear。
spring 集成 mybatis
maven依赖
实体类
mapper文件
数据表和数据
数据库
Spring配置
关联properties文件
数据源
sqlSessionFatory
加载mapper文件
事务管理
测试