本章主要记录MyBatis项目的简单搭建及入门实例,涉及到的知识点有:
- SqlSession:MyBatis数据库连接会话,用来进行数据库操作。
- SqlSessionFactory:MyBatis数据库连接会话工厂,用来打开连接。
- mybatis-config.xml:MyBatis总配置文件(名字随意),用来配置实体类别名、数据源、XML映射文件等。
- XML映射文件:实体对应的SQL配置文件,主要用来配置SQL方法、参数类型、返回类型和SQL语句。
- IDAO:DAO层接口,与XML映射文件乡对应,优化SqlSession的数据库操作方式。
- log4j:日志
MyBatis的配置方式有多种:
- 纯XML配置
- IDAO+XML配置
- 注解+XML配置
- 纯注解
- …
本文只记录前两种实现方式,习惯使用第二种实现方式(IDAO+XML配置)。
1.环境搭建
通过maven-archety-webapp
骨架搭建项目。
1.1.目录结构
src
\---main
\---java
| \---pers
| \---hanchao
| \---himybatis
\---webapp
\---mybatis-mappers //用来存放实体类的映射文件
\---log4j.properties //log4j
\---mybatis-config.xml //MyBatis的总配置文件
1.2.pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>pers.hanchao</groupId>
<artifactId>himybatis</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>himybatis Maven Webapp</name>
<url>http://maven.apache.org</url>
<properties>
<commons-logging.version>1.2</commons-logging.version>
<commons-lang3.version>3.3.2</commons-lang3.version>
<commons-io.version>2.4</commons-io.version>
<log4j.version>1.2.17</log4j.version>
<mysql.version>5.1.40</mysql.version>
<mybatis.version>3.4.5</mybatis.version>
</properties>
<dependencies>
<!--mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
<!--mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<!--log4j-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<!--基本包-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons-lang3.version}</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons-io.version}</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>${commons-logging.version}</version>
</dependency>
</dependencies>
</project>
1.3.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">
<!--MyBatis的总配置文件-->
<configuration>
<!--类型依赖:配置Java类对应的别名-->
<typeAliases>
</typeAliases>
<!--mybatis的数据库连接-->
<environments default="dev">
<environment id="dev">
<!--事务管理-->
<transactionManager type="JDBC"></transactionManager>
<!--数据源信息-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/exam?useSSL=false"/>
<property name="username" value="****"/>
<property name="password" value="****"/>
</dataSource>
</environment>
</environments>
<!--映射xml的路径配置-->
<mappers>
</mappers>
</configuration>
1.4.日志配置log4j.properties
log4j.rootLogger = info,console,file
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
log4j.appender.file = org.apache.log4j.DailyRollingFileAppender
log4j.appender.file.File = himybatis.log
log4j.appender.file.datePattern = '.'yyyy-MM-dd
log4j.appender.file.layout = org.apache.log4j.PatternLayout
log4j.appender.console.file.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
2.纯XML的入门实例
查询id=1的试题信息
2.1.sql
drop table question;
create table `question`(
`id` int(5) unsigned not null auto_increment comment '试题id',
`title` varchar(20) not null comment '题目',
`score` int(3) not null comment '分数',
`answer` varchar(100) comment '答案',
primary key(id)
)engine=InnoDB comment='试题' auto_increment=1 default charset=utf8;
insert into question values(99999,'简答题',100,'你好吗?');
2.2.实体:Question.java
创建试题这个表对应的实体Question
package pers.hanchao.himybatis.hello;
/**
* <p>试题</p>
* @author hanchao 2018/1/26 18:28
**/
public class Question {
/** 试题id */
private Integer id;
/** 题目 */
private String title;
/** 分数 */
private Integer score;
/** 答案 */
private String answer;
//constructor/toString/setter and getter
}
2.3.实体映射XML:Question.xml
在mybatis-mappers
目录下创建Question.xml
。
- 实体映射XML文件中,包含了这个映射的命名域、方法、参数类型、返回类型以及SQL语句。
- 命名域(namespace
)是唯一的,用来让SqlSession
找到这个命名域包含的SQL方法(详见业务代码)。
<?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">
<!--MyBatis的分配置文件,分别对应每个实体,用来配置SQL操作及SQL语句-->
<!--namespace,定义这个映射的命名域,执行映射类(本身不存在)-->
<mapper namespace="pers.hanchao.himybatis.hello.QuestionMapper">
<!--查询语句用select标签-->
<select id="GetQuestionById" parameterType="int" resultType="Question">
SELECT * FROM `question` WHERE id = #{id}
</select>
</mapper>
2.4.在mybatis-config.xml中配置实体及映射文件
<typeAliases>
<!--通过纯XML的配置方式-->
<typeAlias type="pers.hanchao.himybatis.hello.Question" alias="Question"/>
</typeAliases>
//...
<mappers>
<mapper resource="mybatis-mappers/Question.xml"/>
</mappers>
2.5.业务代码:Hello.java
纯XML配置的MyBatis执行过程简述:
- 通过
Reader
读取总配置文件 - 通过配置文件的数据源信息创建
SqlSessionFactory(会话工厂)
- 通过
SqlSessionFactory(会话工厂)
打开SqlSession(会话)
SqlSession(会话)
通过namespace(命名域)
及方法id
找到对应的SQL语句
、参数类型和返回值类型SqlSession(会话)
将参数与SQL语句
组合,形成可执行SQL语句
,执行,将返回结果封装到返回值类型中。SqlSession(会话)
提交(commit
)SqlSession(会话)
关闭(close
)- 结束
package pers.hanchao.himybatis.hello;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.log4j.Logger;
import java.io.Reader;
/**
* <p>简单的MyBaits实例:不依赖Spring和Spring MVC</p>
* @author hanchao 2018/1/26 19:02
**/
public class Hello {
/** MyBatis通过SqlSessionFactory创建SqlSession进而进行数据库操作 */
private static SqlSessionFactory sqlSessionFactory;
/** 读取并加载MyBatis的配置文件 */
private static Reader reader;
private static final Logger LOGGER = Logger.getLogger(Hello.class);
static {
try{
//读取MyBatis的配置文件,总配置文件通过mappers属性依次读取分配置文件
reader = Resources.getResourceAsReader("mybatis-config.xml");
//创建SqlSessionFactory
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
}catch (Exception e){
e.printStackTrace();
LOGGER.error("找不到MyBatis的配置文件!");
}
}
/**
* <p>读取id=99999的试题信息</p>
* @author hanchao 2018/1/26 19:09
**/
public static void main(String[] args) {
//创建SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
try{
//执行查询方法:通过Question.xml找到SQL语句
Question question = sqlSession.selectOne("pers.hanchao.himybatis.hello.QuestionMapper.GetQuestionById",99999);
if (null != question){
//输出结果
LOGGER.info(question.toString());
}
//事务提交
sqlSession.commit();
}catch (Exception e){
//事务回滚
sqlSession.rollback();
}finally {
//关闭连接
sqlSession.close();
}
}
}
2.6.result
2018-01-28 00:09:35 INFO Hello:47 - Question{id=99999, title='简答题', score=100, answer='你好吗?'}
3.XML+IDAO的入门实例
与之前类似的业务场景:查询id=1的难题信息
因为每次执行SQL
都需要拼写namespace(作用域)
和方法id
,很容易发生错误。如下:
//namespace=pers.hanchao.himybatis.hello.QuestionMapper
//方法id=GetQuestionById
//查询参数=99999
Question question = sqlSession.selectOne("pers.hanchao.himybatis.hello.QuestionMapper.GetQuestionById",99999);
为了改善这种查询方式,可以通过DAO层接口的方式进行替代。
3.1.sql
drop table problem;
create table `problem`(
`id` int(5) unsigned not null auto_increment comment '难题id',
`title` varchar(20) not null comment '题目',
`score` int(3) not null comment '分数',
`answer` varchar(100) comment '答案',
primary key(id)
)engine=InnoDB comment='难题' auto_increment=1 default charset=utf8;
insert into problem values(99999,'题目1',100,'你好吗?');
3.2.实体:Problem.java
创建难题这个表对应的实体Problem
package pers.hanchao.himybatis.ihello;
/**
* <p>难题</p>
* @author hanchao 2018/1/26 23:20
**/
public class Problem {
/** 难题id */
private Integer id;
/** 题目 */
private String title;
/** 分数 */
private Integer score;
/** 答案 */
private String answer;
//constructor/toString/setter/getter
}
3.3.IDAO:IProblemDAO.java
创建Problem
的DAO
层接口IProblemDAO.java
,IProblemDAO.java
中定义了查询方法(与XML映射文件一一对应)。
package pers.hanchao.himybatis.ihello;
/**
* <p>实体对应的Dao层接口,与Problem.xml通过namespace建立关联</p>
* @author hanchao 2018/1/26 23:24
**/
public interface IProblemDao {
/** 简单查询 */
Problem getProblemById(Integer id);
}
3.4.实体映射XML:Problem.xml
在mybatis-mappers
目录下创建Problem.xml
。
- 实体映射XML文件中,包含了这个映射的命名域、方法、参数类型、返回类型以及SQL语句。
- 命名域(namespace
)是唯一的,用来让SqlSession
找到这个命名域包含的SQL方法(详见业务代码)。
- 在IDAO+XML
模式中, 命名域(namespace
)就是IDAO
的类路径。
- 方法id
要与IDAO
接口中定义的方法名相互对应
<?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">
<!--MyBatis的分配置文件,分别对应每个实体,用来配置SQL操作及SQL语句-->
<!--namespace,定义这个映射的命名域,这里指向Dao层接口-->
<mapper namespace="pers.hanchao.himybatis.ihello.IProblemDao">
<!--查询语句用select标签-->
<select id="getProblemById" parameterType="int" resultType="Problem">
SELECT * FROM `problem` WHERE id = #{id}
</select>
</mapper>
3.5.在mybatis-config.xml中配置实体及映射文件
<typeAliases>
<!--通过XML+IDao的配置方式,调用方式更方便-->
<typeAlias type="pers.hanchao.himybatis.ihello.Problem" alias="Problem"/>
</typeAliases>
//...
<mappers>
<mapper resource="mybatis-mappers/Problem.xml"/>
</mappers>
3.6.业务代码:IHello.java
IDAO+XML
配置的MyBatis执行过程简述:
- 通过
Reader
读取总配置文件 - 通过配置文件的数据源信息创建
SqlSessionFactory(会话工厂)
- 通过
SqlSessionFactory(会话工厂)
打开SqlSession(会话)
SqlSession(会话)
通过IDAO.class
创建DAO
层的实例化对象,如problemDAO
等等- 通过调用
DAO
层的实例化对象(如problemDAO
)的方法,实现SQL
语句的查询。 SqlSession(会话)
提交(commit
)SqlSession(会话)
关闭(close
)- 结束
package pers.hanchao.himybatis.ihello;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.log4j.Logger;
import java.io.IOException;
import java.io.Reader;
/**
* <p>简单的MyBatis实例:引入了Dao接口概念</p>
* @author hanchao 2018/1/26 23:38
**/
public class IHello {
/** SqlSessionFactory用于创建SqlSession */
private static SqlSessionFactory sqlSessionFactory;
/** Reader用于读取配置文件 */
private static Reader reader;
private static final Logger LOGGER = Logger.getLogger(IHello.class);
static{
try{
//读取MyBatis总配置文件
reader = Resources.getResourceAsReader("mybatis-config.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
} catch (IOException e) {
e.printStackTrace();
LOGGER.error("找不到MyBatis配置文件!");
}
}
/**
* <p>读取id=99999的试题信息</p>
* @author hanchao 2018/1/26 23:42
**/
public static void main(String[] args) {
//创建SqlSession用于数据库会话
SqlSession sqlSession = sqlSessionFactory.openSession();
try{
//通过SqlSession.getMapper直接调用IProblemDao接口
IProblemDao iProblemDao = sqlSession.getMapper(IProblemDao.class);
//通过IProblemDao的定义与IProblem.xml配置的对应关系,找到SQL语句进行执行
Problem problem = iProblemDao.getProblemById(99999);
if (null != problem){
LOGGER.info(problem.toString());
}
//事务提交
sqlSession.commit();
}catch (Exception e){
//事务回滚
sqlSession.rollback();
}finally {
//关闭连接
sqlSession.close();
}
}
}
3.7.result
2018-01-28 00:24:10 INFO IHello:48 - Problem{id=99999, title='题目1', score=100, answer='你好吗?'}