1. 简介
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。
MyBatis 本是apache的一个开源项目iBatis,需要在 Github 上下载。
2. 程序的基本架构
(1)在MySQL中新建一个数据库
(2)通过Maven导Jar包
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.zz</groupId>
<artifactId>MyBatis</artifactId>
<version>1.0-SNAPSHOT</version>
<!--导入依赖-->
<dependencies>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.4</version>
</dependency>
<!--操作数据库-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!--lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
</dependencies>
</project>
(3)编写配置文件,配置数据库连接
在main目录的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">
<configuration>
<!--环境-->
<!--默认开发环境,test为测试环境-->
<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&characterEncoding=utf8&useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
</configuration>
(4)编写一个工具类操作数据库
在main目录的java目录下创建一个工具包util,在包下创建MyBatisUtils类
package com.zz.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 {
String resource = "mybatis-config.xml"; //获取资源
InputStream inputStream = Resources.getResourceAsStream(resource); //把资源变成一个流
// 工厂模式
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
// 从SqlSessionFactory中获取sqlSession的连接
public static SqlSession getSession(){
return sqlSessionFactory.openSession();
}
}
(5)编写一个实体类
在mian目录的java目录下创建一个实体包pojo,在包下创建User类
由于在前面的依赖中导入了Lombok包,就方便了实体类的编写
package com.zz.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private int id;
private String name;
private String pwd;
}
(6)编写一个操作用户的接口类
在mian目录的java目录下创建一个接口包mapper,在包下创建userMapper类
package com.zz.mapper;
import com.zz.pojo.User;
import java.util.List;
// 操作用户的接口类
public interface UserMapper {
List<User> getUserList();
}
(7)编写一个实现接口类的配置文件
在main目录的resources目录下跟java目录下一样,创建一个接口包mapper,在包下创建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.zz.mapper.UserMapper">
<!--id对应接口类中的方法,返回的是一个具体的User,要写包名-->
<!--从user表中查询-->
<select id="getUserList" resultType="com.zz.pojo.User">
select * from user;
</select>
</mapper>
原来我们需要编写接口实现类,使用了Mybatis之后,我们可以专注编写SQL,使用配置文件代替编写接口的实现类。
- 好处,程序运行起来之后,我依旧可以动态修改代码,解耦。
- 注意点:①namespace 绑定对应的接口;②具体操作(CRUD)id对应接口中的方法。
(8)把这个配置文件UserMapper.xml 注册到mybatis-config.xml配置文件中
在configuration标签中添加如下代码:
<mappers>
<mapper resource="com/zz/mapper/UserMapper.xml"/>
</mappers>
(9)测试运行
在test目录下的java目录下创建一个测试类test
import com.zz.mapper.UserMapper;
import com.zz.pojo.User;
import com.zz.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import java.util.List;
public class Test {
public static void main(String[] args) {
// 1、 获取SqlSession, 执行sql使用的
SqlSession session = MyBatisUtils.getSession();
// 2、通过 session.getMapper(Class ) 获得接口
UserMapper mapper = session.getMapper(UserMapper.class);
//3.使用接口中的方法,获得用户列表
List<User> userList = mapper.getUserList();
for (User user : userList) {
System.out.println(user);
}
}
}
运行结果如下:
整个项目的目录如下:
3. CURD 增删改查
- 固定操作
- 编写接口
- 编写接口对应的SQL配置文件,一定要确保配置文件和SQL的正确性
- 编写测试类测试
只需要编写 UserMapper.java、 UserMapper.xml、Test.java文件
(1)通过id 查询用户 User selectById(int id);
在xml 中获取 xx id的写法:id=#{xx}
UserMapper.java文件:
package com.zz.mapper;
import com.zz.pojo.User;
import java.util.List;
// 操作用户的接口类
public interface UserMapper {
//List<User> getUserList();
User selectById(int id);
}
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.zz.mapper.UserMapper">
<!--id对应接口类中的方法,返回的是一个具体的User,要写包名-->
<!--从user表中查询-->
<select id="getUserList" resultType="com.zz.pojo.User">
select * from user;
</select>
<select id="selectById" resultType="com.zz.pojo.User">
select * from user where id=#{1}
</select>
</mapper>
Test.java文件:
import com.zz.mapper.UserMapper;
import com.zz.pojo.User;
import com.zz.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import java.util.List;
public class Test {
public static void main(String[] args) {
// 1、 获取SqlSession, 执行sql使用的
SqlSession session = MyBatisUtils.getSession();
// 2、通过 session.getMapper(Class ) 获得接口
UserMapper mapper = session.getMapper(UserMapper.class);
User user = mapper.selectById(1);
System.out.println(user);
}
}
运行结果:
(2)通过用户名和密码查询用户 User selectByUsernamePwd(@Param("username") String username, @Param("pwd")String pwd);
(其余代码与(1)相同,以下雷同)
UserMapper.java文件:
// 多个参数如何操作,必须要增加注解 @Param
User selectByUsernamePwd(@Param("username") String username, @Param("pwd")String pwd);
UserMapper.xml文件:
<select id="selectByUsernamePwd" resultType="com.zz.pojo.User">
select * from user where name = #{username} and pwd = #{pwd}
</select>
Test.java文件:
User user = mapper.selectByUsernamePwd("小明","123456");
System.out.println(user);
运行结果:
(3)新增一个用户 int addUser(User user);
UserMapper.java文件:
// 新增一个用户 , 对象的情况下,直接可以拿到对象的属性
int addUser(User user);
UserMapper.xml文件:
<insert id="addUser" parameterType="com.zz.pojo.User">
insert into `user`(`id`,`name`,`pwd`) values (#{id},#{name},#{pwd});
</insert>
Test.java文件:
int res = mapper.addUser(new User(4,"小亮","123456"));
session.commit();//提交事务
if(res>0){
System.out.println("增加用户成功!");
}
运行结果:
(4)修改用户信息 int updateUser(User user);
UserMapper.java文件:
// 修改用户信息
int updateUser(User user);
UserMapper.xml文件:
<update id="updateUser" parameterType="com.zz.pojo.User">
update `user` set `name` = #{name},pwd = #{pwd} where id = #{id} ;
</update>
Test.java文件:
int res = mapper.updateUser(new User(4,"小花","123456"));
session.commit();//提交事务
if(res>0){
System.out.println("修改用户成功!");
}
运行结果:
(5)删除一个用户 int deleteUserByID(int id);
UserMapper.java文件:
// 删除用户
int deleteUserById(int id);
UserMapper.xml文件:
<delete id="deleteUserById" parameterType="com.zz.pojo.User">
delete from user where id = #{id}
</delete>
Test.java文件:
int res = mapper.deleteUserById(4);
session.commit();//提交事务
if(res>0){
System.out.println("删除用户成功!");
}
运行结果:
注意点:
(1)多个参数一定要增加 @Param 注解
(2)增删改一定要增加事务提交
(3)增删改,标签一定要对应,参数类型必须要写
(4)增删改不用写返回值,查询,必须写返回值,集合、泛型中的内容(具体的对象)
4. 配置文件
MyBatis的核心配置文件是mybatis-config.xml,它的核心配置结构如下:
元素的标签次序不能修改,必须按照上图的结构顺序!
(1)配置mapppers映射器为扫描包
当有多个配置文件UserMapper.xml 时不用一 一写注册到mybatis-config.xml配置文件中的代码
<mappers>
<package name="com.zz.mapper"/>
</mappers>
(2)配置db.properties 让配置文件读取
在resources目录下创建一个db.properties 文件,代码如下:
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis? useUnicode=true&characterEncoding=utf8&useSSL=false
username=root
password=123456
mybatis-config.xml中的开发环境就可以简化为以下写法:
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
(3)配置类型的别名,简化开发
在mybatis-config.xml中添加包的别名配置
<!--包的别名配置-->
<typeAliases>
<package name="com.zz.pojo"/>
</typeAliases>
所以在UserMapper.xml中就可以简化包的写法,直接写User
<select id="getUserList" resultType="User">
select * from user;
</select>
5. ResultMap结果集映射
处理数据库中的字段名和实体类中的属性名不一致的问题
实体类:
public class User {
private int id;
private String name;
private String password;
}
数据库:
一个是pwd,而另一个是password
在接口的配置文档中xxMapper.xml 中,添加如下代码:
<!-- 结果集映射resultMap,MyBatis推荐的 -->
<resultMap id="UserMap" type="User">
<!-- 数据库字段和实体类属性的映射关系 -->
<id column="id" property="id"/>
<!-- 细节问题: 主键一般使用id标签,其与字段result
column 对应数据库中的列名
property 对应实体类中的属性名
-->
<result column="name" property="name"/>
<result column="pwd" property="password"/>
</resultMap>
<select id="selectUserById" resultMap="UserMap">
select id,name,pwd from user where id = #{id}
</select>
运行结果:
添加了结果集映射后,密码就能查询得出来。
注意:如果属性名和数据库的列名一致 ,这个时候mybatis 会帮我们自动推断!=>自动映射
如果属性名和数据库的列名,不一致 ,手动实现映射
6. 日志
MyBatis中默认的日志:
<settings>
<!--配置日志,就可以看到具体的SQL信息,从而找到出错的原因!-->
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
工作中我们用的更多的 log4j
使用Log4j 步骤
(1)导入包依赖
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
(2)编写log4j的配置文件
在resources目录下创建log4j.properties配置文件,代码如下:
### 设置###
log4j.rootLogger = debug,stdout,D,E
### 输出信息到控制抬 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
### 输出DEBUG 级别以上的日志到=E://logs/error.log ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = ./log/log.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
### 输出ERROR 级别以上的日志到=E://logs/error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =./log/error.log
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR
log4j.appender.E.layout = org.apache.log4j.PatternLayout
(3)修改日志实现为 Log4j,注意大小写问题即可
<settings>
<!--配置日志,就可以看到具体的SQL信息,从而找到出错的原因!
切换为Log4j 的之后,大小写问题,全大写
-->
<setting name="logImpl" value="LOG4J"/>
</settings>
(4)假设我们要使用Log4j 的类去打印日志
import com.zz.mapper.RMapper;
import com.zz.pojo.User;
import com.zz.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.log4j.Logger;
public class Test02{
// 注意导入包的问题 org.apache.log4j.Logger
static Logger logger = Logger.getLogger(Test02.class);
public static void main(String[] args) {
SqlSession session = MyBatisUtils.getSession();
RMapper mapper = session.getMapper(RMapper.class);
System.out.println("1231321222222");// 普通的输出
// 通过log4j 可以将日志实现细粒度的控制;
logger.error("1231321222222"); // 错误信息
logger.info("1231321222222"); // 提示信息
logger.debug("1231321222222");
// 属性名和字段不一致!
User user = mapper.selectUserById(1);
System.out.println(user);
}
}
7. 分页
作用:提高服务器性能!按照一小部分一小部分的来处理我们的数据!
在SQL中使用limt来进行分页
-- 语法
Select * from user limit startIndex,Pagesize
在Java中的分页如下:
(1)接口RMapper中的编写
package com.zz.mapper;
import com.zz.pojo.User;
import java.util.HashMap;
import java.util.List;
// 测试结果集映射问题
public interface RMapper {
// 带分页的操作
// 参数如果超过两个,可以使用map来进行传递指
// key value
List<User> selectUserByLimit(HashMap<String, Integer> map);
}
(2)接口的配置文件RMapper.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.zz.mapper.RMapper">
<!-- 非基本类型之外的数据类型,List,Map,需要显示的定义 -->
<select id="selectUserByLimit" parameterType="map" resultMap="UserMap">
select * from user limit #{startIndex},#{pageSize}
</select>
<!-- 结果集映射resultMap,MyBatis推荐的 -->
<resultMap id="UserMap" type="User">
<!-- 数据库字段和实体类属性的映射关系 -->
<id column="id" property="id"/>
<!-- 细节问题: 主键一般使用id标签,其与字段result
column 对应数据库中的列名
property 对应实体类中的属性名
-->
<result column="name" property="name"/>
<result column="pwd" property="password"/>
</resultMap>
<select id="selectUserById" resultMap="UserMap">
select id,name,pwd from user where id = #{id}
</select>
</mapper>
(3)测试类中的编写
import com.zz.mapper.RMapper;
import com.zz.pojo.User;
import com.zz.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.log4j.Logger;
import java.util.HashMap;
import java.util.List;
public class Test02{
// 注意导入包的问题 org.apache.log4j.Logger
static Logger logger = Logger.getLogger(Test02.class);
public static void main(String[] args) {
SqlSession session = MyBatisUtils.getSession();
RMapper mapper = session.getMapper(RMapper.class);
int currentPage=1; //第几页
int pageSize=2; //每页显示几个
HashMap<String, Integer> map = new HashMap<String, Integer>();
map.put("startIndex",(currentPage-1)*pageSize);
map.put("pageSize",pageSize);
List<User> users = mapper.selectUserByLimit(map);
for (User user : users) {
System.out.println(user);
}
}
}
(4)运行结果