文章目录
这篇文章前面基本上都是看的b站狂神的mybatis写的,后面的话就是我自己个人根据自己实际出现的错误总结的东西了。
视频链接:https://www.bilibili.com/video/BV1NE411Q7Nx?p=2&spm_id_from=pageDriver
MyBatis初步入门
环境:
- JDK 1.8
- Mysql 5.7+
- Maven 3.6.1
- IDEA
学习的最好方式:看官网https://mybatis.org/mybatis-3/zh/index.html
1 简介
1.1 获得Mybatis
在maven中获得Mybatis:
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
1.2 持久层概念
数据持久化:
- 持久化就是将程序的数据在持久状态和瞬时状态转化的过程
- 内存:断电即失
- 数据库(jdbc),io文件持久化
为什么需要持久化?
- 有一些对象,不能让他丢掉。
- 内存太贵
1.3 持久层
dao层,service层,controller层。。。
持久层是什么?
- 完成持久化的代码块
- 层界限十分明显
1.4为什么要Mybatis?
-
帮助程序员将数据存入到数据库中
-
方便
-
传统jdbc太复杂,为了简化、框架、自动化
-
不用mybatis也可以。只要容易上手。技术没有高低之分
优点:
- 简单易学
- 灵活
- sql与代码分离,提高可维护性
- 提供映射标签,支持对象与数据库的orm字段关系映射
- 提供对象关系映射标签,支持对象关系可维护性
- 提供xml标签,支持编写动态sql
最重要的一点:使用的人多!
2 第一个mybatis程序
思路:搭建环境——>导入mybatisjar包——>编写代码——>测试
2.1 搭建环境
创建数据库和表:
CREATE DATABASE `mybatis`;
USE `mybatis`;
CREATE TABLE `user`(
`id` INT(20) NOT NULL PRIMARY KEY,
`name` VARCHAR(30) DEFAULT NULL,
`pwd` VARCHAR(30) DEFAULT NULL
)ENGINE=INNODB DEFAULT CHARSET=utf8;
INSERT INTO `user`(`id`,`name`,`pwd`) VALUES
(1,'qtds','1234'),
(2,'张三','1234'),
(3,'李四','1234')
新建项目
1、新建普通maven项目,创建父工程
2、导入maven依赖
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
2.2 编写配置文件
1、在创建的maven父工程下新建一个新模块
2、编写Mybatis核心配置文件
在资源目录resources下新建一个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>
<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://localhost:3306/mybatis?useUnicode=true&serverTimezone=Asia/Shanghai&characterEncoding=utf8&autoReconnect=true&useSSL=false&allowMultiQueries=true"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
<!-- <property name="driver" value="${driver}"/>-->
<!-- <property name="url" value="${url}"/>-->
<!-- <property name="username" value="${username}"/>-->
<!-- <property name="password" value="${password}"/>-->
</dataSource>
</environment>
</environments>
<!--每一个mapper.xml都需要-在mybatis.config配置文件里面注册-->
<mappers>
<mapper resource="com/qtds/dao/UserMapper.xml"/>
</mappers>
</configuration>
2.3 编写mybatis工具类
在项目源代码Java目录下建包java.qtds.utils
在包下新建一个MybatisUtils类,用于连接mybatis数据库,使用配置文件获取sqlSessionFactory对象
package com.qtds.utils;
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.IOException;
import java.io.InputStream;
public class MybatisUtils {
private static SqlSessionFactory sqlSessionFactory;
static {
try {
//使用mybatis第一步:获取sqlSessionFactory对象
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession();
}
}
2.4 编写mapper接口类与对应配置文件
1、先写一个简单的bean用于封装User类
在com.qtds下新建一个pojo包,在里面新建一个user类
package com.qtds.pojo;
public class User {
private int id;
private String name;
private String pwd;
//此处省略有参无参构造、各字段getset方法及toString方法。
//千万别忘记加了!!!!
}
2、写Mapper接口与对应配置文件(相当于接口实现类)
在com.qtds下新建一个dao包,在里面新建一个UserMapper接口
package com.qtds.dao;
import com.qtds.pojo.User;
import java.util.List;
public interface UserMapper {
List<User> getUserList();
}
再新建一个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接口-->
<mapper namespace="com.qtds.dao.UserMapper">
<!--查询语句-->
<select id="getUserList" resultType="com.qtds.pojo.User">
select * from mybatis.user
</select>
</mapper>
到此为止就是mybatis最基本的操作流程了。
3 测试及常见异常
3.1 编写测试类
使用mybatis进行持久化操作一般都是在service业务逻辑层下用的,这里直接用测试代替业务逻辑层操作
在test目录下的java包内新建com.qtds.dao包,在该包下新建一个UserMapperTest类
package com.qtds.dao;
import com.qtds.pojo.User;
import com.qtds.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.List;
public class UserMapperTest {
@Test
public void test(){
//第一步:获取sqlSession对象
//使用try确保每次sqlSession使用完后都能正常关闭(这里应该是由Java垃圾回收机制关闭).
//这是mybatis官方文档上面的建议操作
try (SqlSession sqlSession = MybatisUtils.getSqlSession()){
//方式一:执行SQL
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> userList = mapper.getUserList();
for (User user : userList) {
System.out.println(user);
}
}
}
@Test
public void test2(){
//第一步:获取sqlSession对象
//一般来说是可以先在外部得到sqlsession再tryfinally的
//得到sqlsession一般来说不会出异常,因为是静态方法,出了异常加载时就会报错
SqlSession sqlSession = MybatisUtils.getSqlSession();
try{
//方式一:执行SQL
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> userList = mapper.getUserList();
//方式二官方文档上有写,但不推荐,在这里就不用了
for (User user : userList) {
System.out.println(user);
}
}finally {
sqlSession.close();
}
}
}
3.2 测试常见异常
1 BuilderException
java.lang.ExceptionInInitializerError
at com.qtds.dao.UserMapperTest.test(UserMapperTest.java:17)<22 internal calls>
Caused by: org.apache.ibatis.exceptions.PersistenceException:
### Error building SqlSession.
### The error may exist in com/qtds/dao/UserMapper.xml
### Cause: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: java.io.IOException: Could not find resource com/qtds/dao/UserMapper.xml
at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
at org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:80)
at org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:64)
at com.qtds.utils.MybatisUtils.<clinit>(MybatisUtils.java:21)
... 23 more
Caused by: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: java.io.IOException: Could not find resource com/qtds/dao/UserMapper.xml
at org.apache.ibatis.builder.xml.XMLConfigBuilder.parseConfiguration(XMLConfigBuilder.java:121)
at org.apache.ibatis.builder.xml.XMLConfigBuilder.parse(XMLConfigBuilder.java:98)
at org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:78)
... 25 more
Caused by: java.io.IOException: Could not find resource com/qtds/dao/UserMapper.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:372)
at org.apache.ibatis.builder.xml.XMLConfigBuilder.parseConfiguration(XMLConfigBuilder.java:119)
... 27 more
测试时也明显写出了最有可能的错误原因:
The error may exist in com/qtds/dao/UserMapper.xml
仔细查看错误代码的末尾的两段可以看出原因是找不到UserMapper.xml配置文件
java.io.IOException: Could not find resource com/qtds/dao/UserMapper.xml
这是因为maven打包时没有将UserMapper.xml打包进来
解决办法:
在父工程或子工程下的pom.xml文件中加入下面的配置语句,使项目下的所有配置文件全部默认打包进target中。
注:一般来说在父工程下加入语句就没问题了,但以防万一在子工程的pom.xml文件中加入也没问题
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
2BindingException
org.apache.ibatis.binding.BindingException: Type interface com.qtds.dao.UserMapper is not known to the MapperRegistry.
一种情况是是在mybatis-config.xml中没有配置好mapper.xml文件,找不到对应配置文件:
还有一种是在UserMapper.xml文件内没有配置好对应接口类:
3 java.lang.NullPointerException
如果说空指针异常的话…hhh,那问题多了去了,自求多福。。。。
当然一般来说按照正常步骤来肯定是没问题的,空指针异常的话仔细看看报错的地方,比如说这样的:
java.lang.NullPointerException
at com.qtds.utils.MybatisUtils.getSqlSession(MybatisUtils.java:29)
那显然是MybatisUtils.getSqlSession方法出了问题,得不到SqlSession,仔细找找MybatisUtils类下的错误,发现是这样的:
public class MybatisUtils {
private static SqlSessionFactory sqlSessionFactory;
static {
try {
//使用mybatis第一步:获取sqlSessionFactory对象
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
//在下面这行出了问题
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession();
}
}
我们的(小写s)sqlSessionFactory属性前面多加了一个类的声明:(大写S)SqlSessionFactory,就导致类内部的sqlSessionFactory属性并没有被赋值,getSqlSession()方法中返回的sqlSessionFactory.openSession()自然就是空的,当然就导致空指针异常了。
在idea里面其实也能看出来sqlSessionFactory并没有被赋值,导致sqlSessionFactory实际显示的是灰色的。
解决办法:去掉那一行的(大写S)SqlSessionFactory。
3.3 测试结果
测试结果如下:
4 结语
基本上mybatis初步的配置就是这么多了,剩下的其实就是利用注解写接口和sql语句了,如果说要用的话应该还是蛮简单的吧,用的多了就习惯了。重点还是要理解起来,重视基础。后面虽说还有扩展文件直接自动写基本的配置文件、接口和bean的,但是还是要重视基础,毕竟关键的sql语句还是要靠手写。当然也是要感谢b站的狂神了,虽然有点啰嗦,但讲的还是蛮好的。