1.简介
关于 Mybatis 框架的介绍请记住如下要点:
- Mybatis 是互联网时代流行的 ORM 框架。
- ORM (Object-Relation Mapping)定义:是一种编程技术,能够实现面向编程语言与关系型数据库之间的数据映射;面向编程语言:常见的如 java、python 等;关系型数据库:常见的如 mysql、oracle;
- Mybatis 是作用于数据层(Dao),可以用来简化 JDBC 操作,实现数据的持久化;
2.入门案例
我们先通过一个实际案例,了解下搭建一个 Mybatis 框架的基本步骤,具体过程如下:
- 第一步:在开发工具 IDEA 中创建一个 Maven 工程,在 pom.xml 文件中引入如下 jar 包;
<!--Mybatis依赖的 jar 包-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<!--访问数据库的JDBC-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>6.0.6</version>
</dependency>
- 第二步:在 mysql 数据库中创建一个表,建表语句如下所示:
create table employee
(
emp_id int not null comment '员工编号'
primary key,
emp_name varchar(50) not null comment '员工姓名',
sex varchar(10) not null comment '性别',
dept_id int not null comment '部门编号',
manager int null comment '经理编号',
hire_date date not null comment '入职日期',
job_id int not null comment '职位编号',
salary decimal(8,2) not null comment '月薪',
bonus decimal(8,2) null comment '奖金',
email varchar(100) not null comment '电子邮箱'
)comment '员工表';
- 第三步:创建与表 employee 具有映射关系的实体类 Employee;
package com.entity;
import java.math.BigDecimal;
import java.util.Date;
/**
* 类注释
*
* @author Lenovo
* @Title: Employee
* @ProjectName mybatisYG
* @Description: TODO 与表 employee 对应
* @date 2019/11/1314:58
*/
public class Employee {
//员工编号
private int empId;
//员工姓名
private String empName;
//员工性别
private String sex;
//部门编号
private int deptId;
//部门经理编号
private int manager;
//入职日期
private Date date;
//职位编号
private int jobId;
//员工月薪
private BigDecimal salary;
//员工奖金
private BigDecimal bonus;
//员工邮箱
private String email;
@Setter
@Getter
@toString
}
- 第四步:创建实体类 Employee 和表 employee 一一对应的映射文件 employeeMapper.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文件的全路径名,不要写.xml后缀-->
<mapper namespace="com.entity.employeeMapper">
<select id="queryEmployeeById" resultType="com.entity.Employee" parameterType="int">
select emp_id empId,emp_name empName,sex,dept_id deptId,manager,hire_date date,
job_id jobId,salary,bonus,email from employee where emp_id = #{empId}
</select>
</mapper>
对以上配置文件说明如下:
★★namespace:值应该为 Mapper 文件的全路径名,注意不要写 .xml后缀;
★★select标签: id 代表唯一区分此SQL的标记,原则上可以随意命名,resultType代表 sql 查询结果的返回值类型,parameterType 为 sql语句中 where 查询条件的数据类型,例如 int;
★★当表中定义的字段与映射实体类中的属性命名不一致时,必须采用别名,将数据库字段映射为实体类属性,例如 employee 表的 emp_id 被映射为实体类 Employee 的属性 empId;
★★注意 where 条件中的参数写法 #{},{}里面的值为实体类的属性值,例如 #{empId};
- 第五步:创建 Mybatis 的配置文件 mybatis-config.xml 文件,文件建议新建在 Resources 文件夹下,配置的具体内容如下所示:
<?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="prod"><!--与 id 值保持一致-->
<environment id="prod"><!--与 defaule 值保持一致-->
<transactionManager type="JDBC"/><!--数据库事务的处理方式,默认为 JDBC-->
<dataSource type="POOLED"><!--数据库连接池类型保持默认值 POOLED-->
<!--配置数据库信息-->
<property name="driver" value="com.mysql.cj.jdbc.Driver"/><!--数据库驱动方式,需要导入 JDBC驱动的 jar 包-->
<property name="url" value="jdbc:mysql://localhost:3306/db?serverTimezone=UTC"/><!--数据库 URL 地址-->
<property name="username" value="root"/><!--数据库用户名-->
<property name="password" value="root"/><!--数据库密码-->
</dataSource>
</environment>
</environments>
<mappers>
<!--加载映射文件,为对应的mapper.xml 文件所在的路径,中间用 / 间隔-->
<mapper resource="com/entity/employeeMapper.xml"/>
</mappers>
</configuration>
★★注意:当数据库驱动采用的是 com.mysql.cj.jdbc.Driver时,此时数据库 URL 后面必须增加 ?serverTimezone=UTC,否则报错;
- 第六步:编写测试类,测试类内容如下:
package com.entity;
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 java.io.Reader;
/**
* 类注释
*
* @author Lenovo
* @Title: TestEmployee
* @ProjectName mybatisYG
* @Description: TODO 测试下简单的查询案例
* @date 2019/11/1317:26
*/
public class TestEmployee {
public static void main(String[] args) throws Exception {
//第一步:加载 Mybatis-config.xml 文件,并使用 字符串输入流 Reader 进行读取;
Reader reader = Resources.getResourceAsReader( "mybatis-config.xml" );
//第二步:创建 SqlSession 的单例工厂
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build( reader );
//第三步:创建访问数据库的Session--connection
SqlSession session = sessionFactory.openSession();
//第四步:找到 待操作的 mapper.xml文件中待执行的 sql 语句,通过 namespace和 select 标签中的id进行定位;
String statement = "com.entity.employeeMapper.queryEmployeeById";
//第五步:执行 SQL 语句
Employee employee = session.selectOne( statement, 2 );
System.out.println( "职工编号为1的员工的基本信息为::" + employee );
//第六步:关闭会话
session.close();
}
}
3.初步搭建案例错误集锦以及解决方案
- 第一个错误:找不到实体类定义的 mapper.xml 文件,具体报错信息如下:
Exception in thread "main" org.apache.ibatis.exceptions.PersistenceException:
### Error building SqlSession.
### The error may exist in com/entity/employeeMapper.xml
### Cause: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: java.io.IOException: Could not find resource com/entity/employeeMapper.xml
at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
at org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:52)
at org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:36)
at com.entity.TestEmployee.main(TestEmployee.java:24)
Caused by: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: java.io.IOException: Could not find resource com/entity/employeeMapper.xml
at org.apache.ibatis.builder.xml.XMLConfigBuilder.parseConfiguration(XMLConfigBuilder.java:121)
at org.apache.ibatis.builder.xml.XMLConfigBuilder.parse(XMLConfigBuilder.java:99)
at org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:50)
... 2 more
Caused by: java.io.IOException: Could not find resource com/entity/employeeMapper.xml
at org.apache.ibatis.io.Resources.getResourceAsStream(Resources.java:114)
at org.apache.ibatis.io.Resources.getResourceAsStream(Resources.java:100)
at org.apache.ibatis.builder.xml.XMLConfigBuilder.mapperElement(XMLConfigBuilder.java:371)
at org.apache.ibatis.builder.xml.XMLConfigBuilder.parseConfiguration(XMLConfigBuilder.java:119)
... 4 more
错误导致原因:在于 maven 工程的 pom.xml 文件中缺少配置,使得编译的时候在 target 目录下加载不到 mapper.xml 文件;
错误解决方案:需要在 pom.xml 文件中增加如下配置;
<build>
<!-- 定义classpath -->
<resources>
<!-- resources文件 -->
<resource>
<directory>src/main/resources</directory>
<!-- 是否被过滤,如果被过滤则无法使用 -->
<filtering>false</filtering>
</resource>
<!-- java文件夹 -->
<resource>
<directory>src/main/java</directory>
<!-- 引入映射文件等 -->
<includes>
<include>**/*.xml</include>
<include>**/*.properties</include>
</includes>
</resource>
</resources>
</build>
- 第二个错误:采用的数据库驱动与数据库 URL 不匹配导致的报错,具体报错信息如下所示:
Caused by: com.mysql.cj.core.exceptions.InvalidConnectionAttributeException: The server time zone value '�й���ʱ��' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to utilize time zone support.
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
错误导致原因:Mysql 依据版本不同,会采用不同的驱动,包括 com.mysql.jdbc.Driver 和 com.mysql.cj.jdbc.Driver,当采用的驱动是 com.mysql.cj.jdbc.Driver 时,此时对应的数据库 URL 地址必须指定时区;
错误解决方法:给 URL 地址加上时区;
<property name="url" value="jdbc:mysql://localhost:3306/db?serverTimezone=UTC"/><!--数据库 URL 地址,此对应的驱动为 com.mysql.cj.jdbc.Driver-->
<property name="url" value="jdbc:mysql://localhost:3306/db"/><!--此 URL 对应的驱动为 com.mysql.jdbc.Driver-->