MyBatis First Demo

实践中入门,MyBatis框架小程序

1. 基本学习

MyBatis的执行流程·:

  1. mybatis配置文件,包括Mybatis全局配置文件和Mybatis映射文件,其中全局配置文件配置了数据源、事务等信息;映射文件配置了SQL执行相关的信息
  2. mybatis通过读取配置文件信息(全局配置文件和映射文件),构造出SqlSessionFactory,即会话工厂
  3. 通过SqlSessionFactory,可以创建SqlSession(即会话,Mybatis是通过SqlSession来操作数据库的)
  4. SqlSession本身不能直接操作数据库,它是通过底层的Executor执行器接口来操作数据库的。Executor接口有两个实现类,一个是普通执行器,一个是缓存执行器(默认)
  5. Executor执行器要处理的SQL信息是封装到一个底层对象MappedStatement中。该对象包括:SQL语句、输入参数映射信息、输出结果集映射信息。其中输入参数和输出结果的映射类型包括java的简单类型、HashMap集合对象、POJO对象类型

2. 环境配置

IDEA Maven项目
数据库环境: MySQL
MyBatisMaven三维坐标

1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.1</version>
</dependency>

3. demo编写

测试代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class UserDaoImpl implements UserDao1 {

// 此处选用namespace为"user",选用此处方法需将UserMapper.xml文件中namespace改过来
public User findUserById(int id) throws Exception {
String resource = "mybatis-config1.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = factory.openSession();
//---------------
User user = session.selectOne("user.findUserById",id); //参数一:namespace.id
//--------------
session.close();
return user;
}
}

Mapper映射配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!--<mapper namespace="user">-->
<mapper namespace="user">
<select id="findAllUsers" resultType="com.yza.demo1.entity.User">
SELECT * FROM USER
</select>
<select id="insertUser" parameterType="com.yza.demo1.entity.User">
INSERT INTO USER(id,userName,password,age) VALUES(#{id},#{userName},#{password},#{age})
</select>
<select id="deleteUserById" parameterType="int" >
DELETE FROM USER WHERE id=#{id}
</select>
<select id="updateUserPassword" parameterType="com.yza.demo1.entity.User">
UPDATE USER SET password=#{password} WHERE id=#{id}
</select>
<select id="findUserById" parameterType="int" resultType="com.yza.demo1.entity.User">
SELECT * FROM USER WHERE id=#{id}
</select>
</mapper>

Mapper接口

1
2
3
4
5
6
7
8
public interface UserDao1 {
public User findUserById(int id) throws Exception;
public List<User> findAllUsers() throws Exception;
public void insertUser(User user) throws Exception;
public void deleteUserById(int id) throws Exception;
public void updateUserPassword(User user) throws Exception;

}

4. 升级版–Mapper代理开发模式

  • Mapper代理的开发方式,程序员只需要编写mapper接口(相当于dao接口),不需再编写dao实现类(Mybatis会自动的为mapper接口生成动态代理实现类)
  • 要实现mapper代理的开发方式,需要遵循一些开发规范(接口的包名,类名,参数,返回值分别对应着映射文件的namespace,id,parameterType,resultType)
  1. mapper接口的全限定名要和mapper映射文件的namespace的值相同
  2. mapper接口的方法名称要和mapper映射文件中的statement的id相同
  3. mapper接口的方法参数只能有一个,且类型要和mapper映射文件中statement的parameterType的值保持一致
  4. mapper接口的返回值类型要和mapper映射文件中statement的resultType值或resultMap中的type值保持一致

UserMapper映射文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?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">

<!-- mapper标签要指定namespace属性,设置为Mapper接口的全路径名-->
<mapper namespace="com.yza.demo1.dao.UserDao">
<select id="findAllUsers" resultType="com.yza.demo1.entity.User">
SELECT * FROM USER
</select>
<select id="insertUser" parameterType="com.yza.demo1.entity.User">
INSERT INTO USER(id,userName,password,age) VALUES(#{id},#{userName},#{password},#{age})
</select>
<select id="deleteUserById" parameterType="int" >
DELETE FROM USER WHERE id=#{id}
</select>
<select id="updateUserPassword" parameterType="com.yza.demo1.entity.User">
UPDATE USER SET password=#{password} WHERE id=#{id}
</select>
<select id="findUserById" parameterType="int" resultType="com.yza.demo1.entity.User">
SELECT * FROM USER WHERE id=#{id}
</select>
</mapper>

Mapper接口

1
2
3
4
5
6
7
public interface UserMapper {
public User findUserById(int id);
public List<User> findUserAll();
public void insertUser(User user);
public void deleteUserById(int id);
public void updateUserPassword(User user);
}

报错1

报错具体信息

1
2
### Error querying database.  Cause: java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for user.findUserById
### Cause: java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for user.findUserById

本质原因–mapper文件的namespace和DaoImpl路径不一致
mapper文件

1
2
3
4
5
6
7
<!-- mapper标签要指定namespace属性,不然会报错,可看做包名 -->
<mapper namespace="com.yza.demo1.dao.UserDao">
<!--<mapper namespace="user">-->
<select id="findUserById" parameterType="int" resultType="com.yza.demo1.entity.User">
select * from user where id=#{id}
</select>
</mapper>

DaoImpl方法–>此处namespace为”user”

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class UserDaoImpl implements UserDao {

public User findUserById(int id) throws Exception {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = factory.openSession();
//---------------
User user = session.selectOne("user.findUserById",id); //参数一:namespace.id
//--------------
session.close();
return user;
}
}

总结:

  • namespace:必须与UserDao的全路径想匹配,这样才能使的接口与sql文件一一对应

报错2

  • 使用Java和MyBatis时遇到的数据无法插入问题
    解决办法–>手动commit

session关闭前不会自动提交

  • 手动commit、close,两次导入数据库,报错
    解决办法:关闭是必须的,就不再提交commit
1
2
3
4
5
6
7
8
9
10
public static void main(String[] args) throws Exception {
SqlSession sqlSession = SqlSessionFactoryUtil.openSession();
UserDao userDao = sqlSession.getMapper(UserDao.class);

User user = new User(3,"yinziyang","111111",22);
userDao.insertUser(user);

//sqlSession.commit();
sqlSession.close();
}

附录:

MyBatisUtil工具类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.*;
import java.io.InputStream;

public class SqlSessionFactoryUtil {

private static SqlSessionFactory sqlSessionFactory;

/**
* 初始化sqlSessionFactory
*/
static {
getSqlSessionFactory();
}

/**
* 获取SqlSessionFactory
* @return
*/
public static SqlSessionFactory getSqlSessionFactory() {
if(sqlSessionFactory==null) {
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream("mybatis-config.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch(Exception e) {
e.printStackTrace();
}
}
return sqlSessionFactory;
}

/**
* 获取SqlSession
* @return
*/
public static SqlSession openSession() {
return sqlSessionFactory.openSession();
}

/**
* 关闭SqlSession
* @param sqlSession
*/
public static void clSSoseSession(SqlSession sqlSession) {
if(sqlSession != null) {
sqlSession.close();
}
}

}

参考

MyBatis学习(1):Mybatis使用详解和入门案例