第一个Mybatis程序
思路(写任何一个程序之前都可以这么考虑):搭建环境–>导入Mybatis–>编写代码–测试!
1.搭建环境
Mybatis是操作数据库的,所以我们先搭建一个测试用的数据库并导入数据;
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,'航哥','123456'),
(2,'张三','123456'),
(3,'李四','123890')
新建项目
- 1.新建一个普通的maven项目(不适用web模板 后面再添加框架支持)
- 2.删除src目录(这样做一个父工程和多个子工程)
- 导入相关的maven依赖
<!--导入依赖-->
<dependencies>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
<!--mybatis依赖-->
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.13</version>
</dependency>
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
</dependency>
</dependencies>
1.2创建一个模块
- 例:创建一个mybatis-01 (作为一个子工程 包规范写好 例把dao pojo utils都写好)
- 在resource下编写mybatis的核心配置文件(mybatis-config.xml)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<!--XML 配置文件中包含了对 MyBatis 系统的核心设置-->
<!--configuration核心配置文件-->
<configuration>
<!--环境-->
<environments default="development">
<!--开发环境-->
<environment id="development">
<transactionManager type="JDBC"/><!--事务管理 默认使用的是JDBC的 决定事务作用域和控制方式的事务管理器-->
<!--获取数据库连接实例的数据源-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8& serverTimezone=Asia/Shanghai"/><!--useSSL=true&需要转义-->
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
<!--测试环境-->
<environment id="test">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!--mappers 元素则包含了一组映射器(mapper),这些映射器的 XML 映射文件包含了 SQL 代码和映射定义信息-->
<!--每一个Mapper.xml都需要在Mybatis核心配置文件中注册 resource绑定mapper需要使用/-->
<mappers>
<mapper resource="com/hang/dao/UserMapper.xml"/>
</mappers>
</configuration>
- 编写mybatis工具类(utils包下)
package com.hang.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;
/**
* sqlSessionFactory(构建sqlSession的)
* 定义一个工具类 把资源加载进来 创建一个能执行sql的对象 整个对象可以想象成一个Connection对象
*/
public class MybatisUtils {
private static SqlSessionFactory sqlSessionFactory;//提升作用域 没事了,
//使用Mybatis第一步:获取sqlSessionFactory对象
static {
try {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//通过build把这个流加载进来
} catch (IOException e) {
e.printStackTrace();
}
}
//既然有了 SqlSessionFactory,顾名思义,我们可以从中获得 SqlSession 的实例
//SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。你可以通过 SqlSession 实例来直接执行已映射的 SQL 语句
public static SqlSession getSqlSession(){
SqlSession sqlSession = sqlSessionFactory.openSession();//会返回一个SqlSession(里面有操作数据库的方法 相当于之前的statement对象)
return sqlSession;
//优化代码:两句可以合成一句(自己合)
}
}
1.3编写代码
- 实体类(pojo包下 对应数据库中字段的! 会lomback可以用lomback)
package com.hang.pojo;
/**
* 实体类
*/
public class User {
private int id;
private String name;
private String pwd;
public User() {
}
public User(int id, String name, String pwd) {
this.id = id;
this.name = name;
this.pwd = pwd;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", pwd='" + pwd + '\'' +
'}';
}
}
- Dao接口(dao包下)
package com.hang.dao;
import com.hang.pojo.User;
import java.util.List;
import java.util.Map;
/**
* 操作数据库的
* Dao==Mapper
*/
public interface UserMapper {
/**
* 查询全部用户
* @return用户列表
*/
List<User> getUserList();
}
- 可以自己写一个UserDaoImpl来对比着学习 看看哪里发生了变化(这里你自己写的时候不用写)
package com.hang.dao;
import com.hang.pojo.User;
import java.util.List;
import java.util.Map;
/*
现在用xml做绑定UserDAO,没有实现这个接口了
原来要重写这个getUserList方法,现在xml中写一个select标签就🆗了 这个标签的id相当于重写了原来的方法
原来这个方法里要写执行sql的语句,现在不用做了 只用执行sql就可以了
*/
public class UserDaoImpl implements UserMapper {
@Override
public List<User> getUserList() {
//之前提取一个BaseDao工具类做这些工作
//Connection
//Statement
String sql="select * from mybatis.user";
//执行完之后还会获取一个结果集ResultSet
return null;//原来需要在这个地方引用JDBC的代码---现在把JDBC的步骤去掉 MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。
}
@Override
public User getUserById(int id) {
return null;
}
@Override
public User getUserById2(Map<String, Object> map) {
return null;
}
@Override
public int addUser(User user) {
return 0;
}
@Override
public int addUser2(Map<String, Object> map) {
return 0;
}
@Override
public int updateUser(User user) {
return 0;
}
@Override
public int deleteUser(int id) {
return 0;
}
@Override
public List<User> getUserLike(String value) {
return null;
}
}
- 接口实现类由原来的Impl变成了一个Mapper配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace=绑定一个对应的Mapper/Dao接口,这个sql想要和UserDao这个接口发生关系-->
<mapper namespace="com.hang.dao.UserMapper">
<!--select查询语句 id对应原来的方法的名字 所有的配置在标签里面-->
<!--resultType代表一个类型 resultMap代表一个集合 一个可以返回多个一个可以返回一个 一般都是resultType 返回结果要写全限定名-->
<select id="getUserList" resultType="com.hang.pojo.User" >
select * from mybatis.user;
</select>
</mapper>
1.4测试
注意点:
org.apache.ibatis.binding.BindingException: Type interface com.hang.dao.UserDao is not known to the MapperRegistry
MapperRegistry是什么?
需要在核心配置文件中注册 mappers(那里)
- 使用junit测试
- 建议:在test包下建一个和项目一样的结构 再在里面写测试案例
package com.hang.dao;
import com.hang.pojo.User;
import com.hang.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class UserMapperTest {
@Test
public void test(){
//原来要获取statement对象执行 现在要去获取sqlsession
//第一步:获得SqlSession对象
SqlSession sqlSession = MybatisUtils.getSqlSession();
//第二步:方式一:getMapper 执行sql 得获取到Dao的这个对象 从sqlSession中获取Mapper
UserMapper userDao = sqlSession.getMapper(UserMapper.class);//得获取UserDao对象 才能去.方法 通过getMapper来获得 通过UserDao接口的Class对象 会返回一个UserDao
List<User> userList = userDao.getUserList();
//方式二:不推荐使用
//List<User> userList = sqlSession.selectList("com.hang.dao.UserMapper.getUserList");
for (User user : userList) {
System.out.println(user);
}
//关闭SqlSession
sqlSession.close();
}
}
可能会遇到的问题
-
配置文件没有注册(会报一个错误出来)
-
绑定接口错误(xml的id那里不要写错了)
-
方法名不对
-
返回类型不对
-
Maven资源导出问题(在pom.xml中加上)
-
<!--在bui1d中配置resources,来防止我们资源导出失败的问题--> <build> <resources> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>false</filtering> </resource> <resource> <!--Maven约定死了这个蓝色的Java里面只能写Java 别的导不出来 我们在这个地方让它可以包含xml properties文件 然后这里面写的文件就可以导出了--> <directory>src/main/java</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <!--让他不去过滤这些东西--> <filtering>false</filtering> </resource> </resources> </build>
- 关于自己在测试中遇到的问题
- 点击运行一直报空指针异常 我的是这么解决的
- 把mysqlconnector mybatis junit依赖换成最新的
- jdbc驱动改成com.mysql.cj.jdbc.Driver
- 工具类中已经定义了成员变量private static SqlSessionFactory sqlSessionFactory 把try语句里面的SqlSessionFactory 声明去掉即可
- 点击运行一直报空指针异常 我的是这么解决的