搭建MyBatis
1.创建maven
工程引入依赖
<dependencies>
<!-- Mybatis核心 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
<!-- junit测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- MySQL驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.3</version>
</dependency>
</dependencies>
mybatis
有两配置文件,一个是核心的配置文件【数据库连接信息和mybatis
全局信息】,一个是mapper
文件用于书写sql
语句
2.创建MyBatis
的核心【全局】配置文件
在习惯上命名为mybatis-config.xml
,这个文件名仅仅是建议,并非强制要求。将来整合Spring
之后,这个配置文件可以省略,所以大家操作时可以直接复制,粘贴。
核心配置文件主要配置连接数据库环境以及mybatis
全局配置信息
核心配置文件存在的位置是src/main/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="development">
<!--设置连接数据库环境-->
<environment id="development">
<!--表示用JDBC管理事务,需要我们手动提交事务-->
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!--引入映射文件-->
<mappers>
<mapper resource="org/mybatis/example/BlogMapper.xml"/>
</mappers>
</configuration>
3.创建Mapper
接口
1.必须先创建数据库中的表:
CREATE TABLE IF NOT EXISTS t_user(
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(20),
`password` VARCHAR(20),
age INT,
sex CHAR,
email VARCHAR(20)
);
2.创建对应的javabean
类
public class User {
private int id;
private String username;
private String password;
private int age;
private String sex;
private String email;
public User() {
}
public User(int id, String username, String password, int age, String sex, String email) {
this.id = id;
this.username = username;
this.password = password;
this.age = age;
this.sex = sex;
this.email = email;
}
public int getId() {
return id;
}
public void setId(int 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;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", age=" + age +
", sex='" + sex + '\'' +
", email='" + email + '\'' +
'}';
}
}
MyBatis
中的mpper
接口相当于以前的dao
,但是区别在于mapper
仅仅是接口,我们不需要提供实现类,在mybatis
会自动生成实现类
public interface UserMapper {
/**
* 添加用户信息
*/
int insertUser();
}
4.创建MyBatis
的映射文件
相关概念:ORM
【Object Relationship Mapper
】对象关系映射。
- 对象:
Java
的实体类对象 - 关系:关系型数据库
- 映射:二者之间的对应关系
Java 概念 | 数据库概念 |
---|---|
类 | 表 |
属性 | 字段/列 |
对象 | 记录/行 |
细节说明
1.映射文件的命名规则:
- 表所对应的实体类的类名+
Mapper.xml
【就是mapper
接口中的接口名和映射文件的名字一致,只是后缀不同】 - 例如:表名为
t_User
,映射的实体类为User
,所对应的接口名一般为UserMapper
,及对应的映射文件为UserMapper.xml
,所以说:接口名和映射文件名一致只是后缀不同,一个是.java
,一个是.xml
- 一个映射文件对应一个实体类,对应一张表的操作
mybatis
映射文件用于编写sql
,访问以及操作表中的数据mybatis
映射文件存放的位置是src/main/resources/mappers
目录下【注意在resources
下文件是以目录形式的不能使用.
形式,要以\
形式】
2.MyBatis
中可以面向接口操作数据,要保证两个一致性:[非常重要]
mapper
接口的全类名和映射文件的命名空间namespace
保持一致mapper
接口中的方法的方法名和映射文件中编写sql
的标签的id
属性保持一致
原因是:我们调用mapper
接口时,mapper
接口可以根据映射文件的命名空间namespace
找到mapper.xml
文件,再调用mapper
接口中的方法时,根据映射文件中的id
可以找到相对应的sql
标签,从而执行sql
注意是在:resources
下存放的是资源文件,不是包,所以不能使用.
的方式,要以目录的方式\
第一步:编写Mapper
接口
public interface UserMapper {
/**
* MyBatis面向接口编程的两个一致:
* 1、映射文件的namespace要和mapper接口的全类名保持一致
* 2、映射文件中SQL语句的id要和mapper接口中的方法名一致
*
* 表--实体类--mapper接口--映射文件
*/
/**
* 添加用户信息
*/
int insertUser();
}
第二步:编写Mapper.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">
<mapper namespace="com.haikang.mapper.UserMapper">
<!--
int insertUser();
方法名要与id一致,否则查找不到相应的sql语句
-->
<insert id="insertUser">
insert into t_user(id,username,password,age,sex,email)
values(null,"湛江","123",23,"男","123@qq.com")
</insert>
</mapper>
第三步:在mybatis
核心【全局】配置文件中引入 mapper.xml
的路径
<!--引入映射文件-->
<!--注意是:不能使用`.`的方式,
因为在`resources`下是以目录的形式的,不是以包的形式,所以要以`\`的形式
-->
<mappers>
<mapper resource="mappers/UserMapper.xml"/>
</mappers>
5.通过Junit
测试功能
步骤:
- 读取
MyBatis
的核心配置文件【使用的是apache
中的ibatis.io
包下的Resources
类】 - 创建
SqlSessionFactoryBuilder
对象 - 通过核心配置文件所对应的字节输入流创建工厂类
SqlSessionFactory
,生产SqlSession
对象 - 使用
SqlSessionFactory
对象中的静态方法openSession()
,获取SqlSession
对象【注意是在openSession()
方法中可以传入参数,传入true
表示自动提交事务,传入false
表示手动提交事务】 - 调用
SqlSession
对象中的getMapper(Class<T> type)
方法,返回一个实现类,如果传入是一个类,则返回一个类的对象,如果传入是一个接口,则返回的是一个接口的实现类 - 调用
Mapper
接口中的方法 - 处理结果
- 关闭流
上述第五小点
// 5. 调用`SqlSession`对象中的`getMapper(Class<T> type)`方法,返回一个实现类,如果传入是一个类,则返回一个类的对象,如果传入是一个接口,则返回的是一个接口的实现类
// 如果传入是一个Java具类,返回就是一个Java类的对象
User user = new User();
sqlSession.getMapper(User.class);
// 如果传入是一个接口,返回就是一个接口的实现类对象
UserMapper mapper = sqlSession.getMapper(UserMapper.class);//返回一个接口的实现类的对象
案例:
/**
* @Author 海康
* @Version 1.0
*/
public class TestMapperCRUD {
@Test
public void testInsert() throws IOException {
// 1. 读取`MyBatis`的核心配置文件
InputStream rss = Resources.getResourceAsStream("mybatis-config.xml");
// 2. 创建`SqlSessionFactoryBuilder`对象
SqlSessionFactoryBuilder ssfb = new SqlSessionFactoryBuilder();
// 3. 通过核心配置文件所对应的字节输入流创建工厂类`SqlSessionFactory`,生产`SqlSession`对象
SqlSessionFactory build = ssfb.build(rss);
// 4. 使用`SqlSessionFactory`对象中的静态方法`openSession()`,获取`SqlSession`对象【注意是在`openSession()`方法中可以传入参数,传入`true`表示自动提交事务,传入`false`表示手动提交事务】
SqlSession sqlSession = build.openSession();
// 5. 调用`SqlSession`对象中的`getMapper(Class<T> type)`方法,返回一个实现类,如果传入是一个类,则返回一个类的对象,如果传入是一个接口,则返回的是一个接口的实现类
// 如果传入是一个Java具类,返回就是一个Java类的对象
// User user = new User();
// sqlSession.getMapper(User.class);
// 如果传入是一个接口,返回就是一个接口的实现类对象
UserMapper mapper = sqlSession.getMapper(UserMapper.class);//返回一个接口的实现类的对象
// 6. 调用`Mapper`接口中的方法
int i = mapper.insertUser();
//注意是:由于使用的是JDBC管理事务,需要手动提交事务,除非在获取SqlSession对象中传入true参数
sqlSession.commit();
// 7. 处理结果
System.out.println(i);
}
}
执行的原理是:当我们调用方法时,会根据接口,接口找到相应的web.xml
,接口的方法会根据web.xml
的id
对应的Sql
语句,执行sql
总结:
SqlSession
:代表Java
程序和数据库之间的会话。【相当于HttpSession
是Java
程序和浏览器之间的会话】
SqlSessionFactory
:是生产
SqlSession
的工厂
工厂模式:如果创建某个一个对象,使用的过程基本固定,那么我们就可以把创建这个对象的相关代码封装到一个工厂类
中,以后都使用这个 工厂类来生产
我们需要对象
优化自动提交事务
在使用SqlSessionFactory
对象中的一个openSession()
方法时,传入参数true
时,表示自动提交,不需要手动提交事务
6.加入log4j
日志功能
步骤:
-
加入依赖
-
加入
log4j
的配置文件log4j
配置文件名为log4j.xml
,存放位置src/main/resources
目录下【一般日志文件名是固定的】
依赖:
<!-- log4j日志 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
加入log4j
配置文件【文件名一般是固定的】
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
<param name="Encoding" value="UTF-8" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-5p %d{MM-dd HH:mm:ss,SSS}
%m (%F:%L) \n" />
</layout>
</appender>
<logger name="java.sql">
<level value="debug" />
</logger>
<logger name="org.apache.ibatis">
<level value="info" />
</logger>
<root>
<level value="debug" />
<appender-ref ref="STDOUT" />
</root>
</log4j:configuration>
日志的级别【重点】
FATAL
(致命) —> ERROR
(错误) —> WARN
(警告) —> INFO(信息) —>DEBUG
(调试)
从左到右打印的内容越来越详细
7.测试增删改查CRUD
书写的顺序,是先在Mapper
接口中,定义方法,再在Mapper.xml
文件中编写sql
语句
第一步:编写UserMapper
接口
public interface UserMapper {
/**
* MyBatis面向接口编程的两个一致:
* 1、映射文件的namespace要和mapper接口的全类名保持一致
* 2、映射文件中SQL语句的id要和mapper接口中的方法名一致
*
* 表--实体类--mapper接口--映射文件
*/
/**
* 添加用户信息
*/
int insertUser();
/**
* 修改用户信息
*/
int updateUser();
/**
* 删除用户信息
*/
int deleteUser();
/**
* 根据ID查询用户信息
*/
User getUserById();
/**
* 查询所有用户信息
*/
List<User> selectAllUser();
}
第二步:编写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">
<mapper namespace="com.haikang.mapper.UserMapper">
<!--
int insertUser();
方法名要与id一致,否则查找不到相应的sql语句
-->
<insert id="insertUser">
insert into t_user(id,username,password,age,sex,email)
values(null,"海康","123",22,"男","123@qq.com");
</insert>
<!--修改用户信息:int updateUser();-->
<update id="updateUser">
update t_user set email = "168@qq.com" where id = 1;
</update>
<!--删除用户信息int deleteUser();-->
<delete id="deleteUser">
delete from t_user where id = 2;
</delete>
<!--查询指定用户信息User getUserById();-->
<!--
在查询时,如果没有指定返回映射关系,则会报以下错误,原因是查询到的结果,mybatis不知道
向哪个类中封装实体类对象,所以报了:Result Type nor a Result Map was specified 不明确
It's likely that neither a Result Type nor a Result Map was specified.
-->
<!--
在查询语句中必须要指定映射关系,可以指定为 resultType类型或resultMap类型
resultType为默认映射类型,会根据属性找到成员属性进行赋值封装实体类
resultMap为自定义映射类型,会自定义映射关系
-->
<select id="getUserById" resultType="com.haikang.dao.User">
select * from t_user where id = 1;
</select>
<!--查询所有用户信息 List<User> selectAllUser()-->
<select id="selectAllUser" resultType="com.haikang.dao.User">
select * from t_user;
</select>
</mapper>
第三步:编写测试方法
/**
* @Author 海康
* @Version 1.0
*/
public class TestMapperCRUD {
@Test
public void testInsert() throws IOException {
// 1. 读取`MyBatis`的核心配置文件
InputStream rss = Resources.getResourceAsStream("mybatis-config.xml");
// 2. 创建`SqlSessionFactoryBuilder`对象
SqlSessionFactoryBuilder ssfb = new SqlSessionFactoryBuilder();
// 3. 通过核心配置文件所对应的字节输入流创建工厂类`SqlSessionFactory`,生产`SqlSession`对象
SqlSessionFactory build = ssfb.build(rss);
// 4. 使用`SqlSessionFactory`对象中的静态方法`openSession()`,获取`SqlSession`对象【注意是在`openSession()`方法中可以传入参数,传入`true`表示自动提交事务,传入`false`表示手动提交事务】
SqlSession sqlSession = build.openSession();
// 5. 调用`SqlSession`对象中的`getMapper(Class<T> type)`方法,返回一个实现类,如果传入是一个类,则返回一个类的对象,如果传入是一个接口,则返回的是一个接口的实现类
// 如果传入是一个Java具类,返回就是一个Java类的对象
// User user = new User();
// sqlSession.getMapper(User.class);
// 如果传入是一个接口,返回就是一个接口的实现类对象
UserMapper mapper = sqlSession.getMapper(UserMapper.class);//返回一个接口的实现类的对象
// 6. 调用`Mapper`接口中的方法
int i = mapper.insertUser();
//注意是:由于使用的是JDBC管理事务,需要手动提交事务,除非在获取SqlSession对象中传入true参数
sqlSession.commit();
// 7. 处理结果
System.out.println(i);
// 关闭流
if (sqlSession!=null){
sqlSession.close();
}
}
@Test
public void testUpdate() throws IOException {
// 加载配置文件
InputStream rss = Resources.getResourceAsStream("mybatis-config.xml");
// 创建工厂对象
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
// SqlSessionFactoryBuilder对象中的build方法获取一个SqlSessionFactory对象
SqlSessionFactory build = sqlSessionFactoryBuilder.build(rss);
// 获取SqlSession对象
SqlSession sqlSession = build.openSession(true);//传入true表示自动提交事务
// 获取Mapper接口实现类对象
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// 调用Mapper接口中的方法
int i = mapper.updateUser();
// 处理结果
System.out.println(i);
// 关闭流
if (sqlSession!=null){
sqlSession.close();
}
}
@Test
public void testDelete() throws IOException {
// 加载配置文件
InputStream rss = Resources.getResourceAsStream("mybatis-config.xml");
// 创建工厂对象
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
// SqlSessionFactoryBuilder对象中的build方法获取一个SqlSessionFactory对象
SqlSessionFactory build = sqlSessionFactoryBuilder.build(rss);
// 获取SqlSession对象
SqlSession sqlSession = build.openSession(true);//传入true表示自动提交事务
// 获取Mapper接口实现类对象
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// 调用Mapper接口中的方法
int i = mapper.deleteUser();
// 处理结果
System.out.println(i);
// 关闭流
if (sqlSession!=null){
sqlSession.close();
}
}
@Test
public void testSelect() throws IOException {
// 加载配置文件
InputStream rss = Resources.getResourceAsStream("mybatis-config.xml");
// 创建工厂对象
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
// SqlSessionFactoryBuilder对象中的build方法获取一个SqlSessionFactory对象
SqlSessionFactory build = sqlSessionFactoryBuilder.build(rss);
// 获取SqlSession对象
SqlSession sqlSession = build.openSession(true);//传入true表示自动提交事务
// 获取Mapper接口实现类对象
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// 查询指定用户信息
// User user = mapper.getUserById();
// 处理结果
// System.out.println(user);
// 查询所有用户信息
List<User> users = mapper.selectAllUser();
// 输出所有用户信息
users.forEach(user -> System.out.println(user));
// 关闭流
if (sqlSession!=null){
sqlSession.close();
}
}
注意:
- 查询标签
select
必须设置属性resultType
或resultMap
,用于设置实体类和数据库表的映射关系resultType
:自动映射,用于属性名和表中字段名一致的情况resultMap
:自定义映射,用于一对多或多对一或字段名和属性名不一致的情况
- 当查询的数据为多条时,不能使用实体类作为返回值,只能使用集合,否则会抛出异常
ToomManyResultsException
,但是若查询的数据只有一条,可以使用实体类或集合作为返回值