一、MyBatis介绍
1、三层架构
三层架构不是一种实际的技术,而是一种的符合“高内聚,低耦合”思想,它把各个功能模块划分为表示层(UI)、业务逻辑层(BLL)和数据访问层(DAL)三层架构,各层之间采用接口相互访问,并通过对象模型的实体类(Model)作为数据传递的载体,不同的对象模型的实体类一般对应于数据库的不同表,实体类的属性与数据库表的字段名一致。
三层架构区分层次的目的是为了 “高内聚,低耦合”,使分工更明确,从而·将精力更专注于应用系统核心业务逻辑的分析、设计和开发,加快项目的进度,提高了开发效率,有利于项目的更新和维护工作。如下:
每个层所负责的功能如下:
- 表现层(UI):即展现给用户的界面,负责接收用户信息和给用户显示用户信息的功能,即用户在使用一个系统的时候它的所见所得。
- 业务逻辑层(BLL):针对具体问题的操作,也可以说是对数据层的操作,对数据业务逻辑进行处理。
- 数据访问层(DAL):该层直接操作数据库,针对数据的增添、删除、修改、更新、查找等。
传统的数据访问层的解决方案有:JDBC、JdbcTemplate以及DButils。JDBC是一种规范,而JdbcTemplate和DBUtils只是工具类。MyBatis是用于数据访问层的框架,是对jdbc的封装,它让数据库底层操作变的透明。下面将对MyBatis做详细的介绍。
2、MyBatis介绍
(1)概念
MyBatis是一个优秀的基于Java的持久层框架,它封装了JDBC操作的很多细节,使开发者只需要关注SQL语句本身,而无需关注注册驱动、创建连接等复杂过程。它使用ORM思想实现了结果集的封装。ORM思想(Object Relational Mapping,对象关系映射)把数据库表和实体类以及实体类的属性对应起来,从而可以通过操作实体类就实现操作数据库表。
Mybatis可以将Sql语句配置在XML文件中,避免将Sql语句硬编码在Java类中。它与JDBC相比:
- Mybatis通过参数映射方式,可以将参数灵活的配置在SQL语句中的配置文件中,避免在Java类中配置参数(JDBC)
- Mybatis通过输出映射机制,将结果集的检索自动映射成相应的Java对象,避免对结果集手工检索(JDBC)
- Mybatis可以通过Xml配置文件对数据库连接进行管理。
(2)优点:
- 相比于 JDBC 需要编写的代码更少
- 使用灵活,支持动态 SQL
- 提供映射标签,支持对象与数据库的字段关系映射
(3)缺点:
- SQL 语句依赖于数据库,数据库移植性差
- SQL 语句编写工作量大,尤其在表、字段比较多的情况下
二、MyBatis的入门程序
MyBatis的实现方式有两种:一种是基于XML方式的;另一种则是基于注解方式实现。这里的入门程序将以XML方式实现,注解方式会在后续文章更新的过程中去完成。
(1)创建数据库表t_user,并插入数据
create table t_user(
id int primary key auto_increment,
username varchar(20),
password varchar(20));
insert into t_user(username, password) values("张三", "zhangsan123");
insert into t_user(username, password) values("李四", "lisi123");
insert into t_user(username, password) values("tom", "123456");
insert into t_user(username, password) values("jerry", "jerry123456");
(2)在pom.xml中引入jar包的依赖。
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.25</version>
</dependency>
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
(3)在resources目录下创建 log4j.properties 文件。
### 设置###
log4j.rootLogger = debug,stdout
### 输出信息到控制抬 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
pender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
(4)创建实体类User
public class User {
private Integer id;
private String username;
private String password;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
(5)创建接口类IUserDao。
public interface IUserDao {
List<User> findAll();
}
(6)在 resource目录下创建一个名为 com.day1.dao的层级目录,在该包中创建映射文件 userMapper.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">
<!--namespace:指定了唯一的命名空间-->
<mapper namespace="com.day1.dao.IUserDao">
<!--
id和接口中的方法名一致
resultType返回值的参数类型
-->
<select id="findAll" resultType="com.day1.entity.User">
select * from t_user;
</select>
</mapper>
在上述映射文件中,<mapper> 元素是配置文件的根元素,它包含了一个 namespace 属性,该属性值通常设置为“包名+SQL映射文件名”,指定了唯一的命名空间。子元素 <select> 中的信息是用于执行查询数据库所有数据的配置。
(7)创建 MyBatis 的配置文件SqlMapperConfig.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="mysql">
<!-- 配置MySQL的环境 -->
<environment id="mysql">
<!-- 配置事务的类型 -->
<transactionManager type="JDBC"></transactionManager>
<!-- 配置数据源(连接池) -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///universaldb"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!-- 指定映射的配置文件位置:每一个都是独立的文件 -->
<mappers>
<mapper resource="com/day1/userMapper.xml"></mapper>
</mappers>
</configuration>
(8)创建测试类
public class MyBatisTest {
@Test
public void testFindAll() throws IOException {
//1、读取配置文件
InputStream in = Resources.getResourceAsStream("SqlMapperConfig.xml");
//2、创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
//3、使用工厂生产SqlSession对象
SqlSession sqlSession = factory.openSession();
//4、使用SqlSession创建dao接口的代理对象
IUserDao userDao = sqlSession.getMapper(IUserDao.class);
//5、使用代理对象执行方案
List<User> allUser = userDao.findAll();
for(User user : allUser){
System.out.println(user);
}
//6、释放资源
sqlSession.close();
in.close();
}
}
执行结果如下:
几点说明:
(1)MyBatis的工作流程
Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatemnt、CallableStatement)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。后面将详细分析。
(2)MyBatis的配置文件
- SqlMapConfig.xml是mybatis全局配置文件,名称不固定,用来配置运行环境,如:数据源、事务等。
- 类名+mapper.xml 主要用来配置sql语句。
(3)错误总结·
报错信息:A query was run and no Result Maps were found for the Mapped Statement
原因:parameterType是执行sql时传入的参数,resuyltType是查询结果返回的数据类型,我误将resuyltType写成了parameterType。
解决方案:将parameterType改为resuyltType,因为查询数据库中数据表的所有信息并不需要传参。