MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。
iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。
MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作
。MyBatis 可以通过简单的 XML或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)
为数据库中的记录。
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')
<dependencies>
<!-- 导入依赖 -->
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<!-- 数据库的版本一定要一致>
<version>5.1.47</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
<scope>provided</scope>
</dependency>
</dependencies>
<?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 代表一个具体环境-->
<environment id="development">
<!-- transactionManager 事物管理器-->
<transactionManager type="JDBC"/>
<!-- dataSource 数据源的配置-->
<dataSource type="POOLED">
<!-- 连接数据库的配置-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=utf-8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<!-- resource 资源对应的路径-->
<mapper resource="com/li/mapper/UserMapper.xml"/>
</mappers>
</configuration>
public class Utils {
private static SqlSessionFactory sqlSessionFactory;
static {
try {
//指定全局配置文件
String resource = "mybatis-config.xml";
//读取配置文件
InputStream inputStream = Resources.getResourceAsStream(resource);
//构建sqlSessionFactory
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
//获取SqlSession
public static SqlSession getSession() {
return sqlSessionFactory.openSession();
}
}
实体类用了lombo:
kLombok项目是一个Java库,它会自动插入编辑器和构建工具中,Lombok提供了一组有用的注释,用来消除Java类中的大量样板代码。仅五个字符(@Data)就可以替换数百行代码从而产生干净,简洁且易于维护的Java类。
@Data: 注解在类,生成setter/getter、equals、canEqual、hashCode、toString方法,如为final属性,则不会为该属性生成setter方法。
@NoArgsConstructor: 注解在类,生成无参的构造方法。
@AllArgsConstructor: 注解在类,生成包含类中所有字段的构造方法。
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private int id;
private String pwd;
private String name;
}
//操作用户的接口
public interface UserMapper {
List<User> getUserList();
}
<?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">
<!--编写具体的sql namespace 命名空间 包名+接口名-->
<mapper namespace="com.li.mapper.UserMapper">
<!-- id 与方法一致 resultType 结果类型具体到包名 -->
<select id="getUserList" resultType="com.li.pojo.User">
select * from user ;
</select>
</mapper>
public class test {
public static void main(String[] args) {
//获得SqlSession对象
SqlSession session = Utils.getSession();
//通过session.getMapper()获得接口
UserMapper mapper = session.getMapper(UserMapper.class);
List<User> userList = mapper.getUserList();
for (User user : userList) {
System.out.println(user);
}
}
}
测试结果:
User(id=1, pwd=123456, name=王麻子)
User(id=2, pwd=123456, name=张三)
User(id=3, pwd=123890, name=李四)
Process finished with exit code 0
对UserMapper接口进行编写CURD代码,代码如下:
//操作用户的接口
public interface UserMapper {
List<User> getUserList();
//根据用户的Id查询
User selectById(int id);
//多个参数的查询 必须加@Param(形参值)
User selectByUsernamePwd(@Param("username") String username, @Param("pwd") String pwd);
//新增用户
int addUser(User user);
//修改用户信息
int updateUser(User user);
//根据用户Id删除用户信息
int deleteUserById(int id);
}
对UserMapper.xml 文件编写sql代码
<?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">
<!--编写具体的sql namespace 命名空间 包名+接口名-->
<mapper namespace="com.li.mapper.UserMapper">
<!-- id 与方法一致 resultType 结果类型具体到包名 -->
<select id="getUserList" resultType="com.li.pojo.User">
select * from user ;
</select>
<select id="selectById" resultType="com.li.pojo.User">
select * from user where id = #{id}
</select>
<select id="selectByUsernamePwd" resultType="com.li.pojo.User">
select * from user where name = #{username} and pwd = #{pwd}
</select>
<insert id="addUser" parameterType="com.li.pojo.User">
insert into `user`(`id`,`name`,`pwd`) values(#{id},#{name},#{pwd});
</insert>
<update id="updateUser" parameterType="com.li.pojo.User">
update `user` set name = #{name}, pwd = #{pwd} where id = #{id};
</update>
<delete id="deleteUserById" parameterType="int">
delete from user where id = #{id}
</delete>
</mapper>
进行测试:
public class test {
public static void main(String[] args) {
//获得SqlSession 对象
SqlSession session = Utils.getSession();
//通过session.getMapper()获得接口
UserMapper mapper = session.getMapper(UserMapper.class);
//查询所有用户信息
List<User> userList = mapper.getUserList();
for (User user : userList) {
System.out.println(user);
}
//根据用户id查询
User user = mapper.selectById(1);
System.out.println(user);
//根据用户的姓名,密码查询
User user1 = mapper.selectByUsernamePwd("张三", "123456");
System.out.println(user1);
//新增用户
int res = mapper.addUser(new User(4, "刘德华", "19600808"));
//提交事务
session.commit();
if (res > 0) {
System.out.println("增加成功!");
}
//修改用户信息
int res = mapper.updateUser(new User(4, "周星驰 ", "987654"));
//提交事务
session.commit();
if (res > 0) {
System.out.println("修改成功!");
}
//删除指定用户
int res = mapper.deleteUserById(4);
//提交事务
session.commit();
if (res > 0) {
System.out.println("删除成功!");
}
}
}
注意事项:
1.增删改必须要提交事务
2.增删改没有返回值,查询有返回值
3.如果查询结果为null 说明字符集编码的问题
4.多个参数用@Param 注解
<!-- 绑定mapper配置文件的几种方式:-->
<!-- 1.resource 资源对应的路径-->
<!-- 2.class 接口对应的路径 UserMapper.xml UserMapper在同一包下 -->
<!-- 3.package 接口很多可以扫描包 -->
<mappers>
<!--<mapper resource="com/li/mapper/UserMapper.xml"/>-->
<!--<mapper class="com.li.mapper.UserMapper"/>-->
<package name="com.li.mapper"/>
</mappers>
<!-- properties 属性读取外部资源-->
<properties resource="db.properties"/>
外部资源:db.properties的配置
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=utf-8
username=root
password=123456
<!--typeAliases 类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写-->
<typeAliases>
<!--<package name="com.li.pojo"/>-->
<typeAlias type="com.li.pojo.User" alias="User"/>
</typeAliases>
对应的UserMapper.xml 文件配置
<select id="selectById" resultType="User">
select * from user where id = #{id}
</select>
<settings>
<!-- 指定 MyBatis 所用日志的具体实现,未指定时将自动查找。配置日志 查看具体sql信息,方便查错-->
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
注意: mybatis-config.xml 配置文件中有层级结构
问题:如果sql中的列名与实体类的属性名不一致?如何解决?
方式一:设置列别名
<select id="selectUserById" resultType="User">
select id,name,pwd as password from user where id = #{id}
</select>
方式二:结果映射 ResultMap
<resultMap id="userResultMap" type="User">
<!-- 主键一般使用id标签 其余使用result标签 -->
<!--
property 对应实体类的属性名
column 对应数据库的列名
-->
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="password" column="pwd"/>
</resultMap>
<select id="selectUserById" resultMap="userResultMap">
select id,name,pwd from user where id = #{id}
</select>
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
### 设置###
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
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
<settings>
<!-- 指定 MyBatis 所用日志的具体实现,未指定时将自动查找。配置日志 查看具体sql信息,方便查错-->
<setting name="logImpl" value="LOG4J"/>
</settings>
public class Test2 {
//注意导包的问题一定是 org.apache.log4j
static Logger logger = Logger.getLogger(Test2.class);
public static void main(String[] args) {
//获取sqlsession
SqlSession session = Utils.getSession();
//获取接口的对象
ResultMapper mapper = session.getMapper(ResultMapper.class);
User user = mapper.selectUserById(1);
logger.debug("This is a debug Message");
logger.error("This is a error Message");
logger.info("This is a info Message");
System.out.println(user);
}
}
在学习mybatis等持久层框架的时候,会经常对数据进行增删改查操作,使用最多的是对数据库进行查询操作,如果查询大量数据的时候,我们往往使用分页进行查询,也就是每次处理小部分数据,这样对数据库压力就在可控范围内。
分页接口
public interface ResultMapper {
//分页操作
List<User> selectUserByLimit(Map<String,Integer> map);
}
ResultMapper.xml文件
<select id="selectUserByLimit" parameterType="map" resultMap="userResultMap">
select * from user limit #{startIndex}, #{PageSize}
</select>
测试
public class Test2 {
//注意导包的问题一定是 org.apache.log4j
static Logger logger = Logger.getLogger(Test2.class);
public static void main(String[] args) {
//获取sqlsession
SqlSession session = Utils.getSession();
//获取接口的对象
ResultMapper mapper = session.getMapper(ResultMapper.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> user = mapper.selectUserByLimit(map);
for (User user1 : user) {
System.out.println(user1);
}
}
}
分页接口
public interface ResultMapper {
//分页操作
List<User> selectUserByLimit(Map<String,Integer> map);
}
ResultMapper.xml文件
<select id="selectUserByLimit" parameterType="map" resultMap="userResultMap">
select * from user ;
</select>
测试
public class Test2 {
//注意导包的问题一定是 org.apache.log4j
static Logger logger = Logger.getLogger(Test2.class);
public static void main(String[] args) {
//获取sqlsession
SqlSession session = Utils.getSession();
int currentPage = 1;//第几页
int PageSize = 2;//每页显示几个
RowBounds rowBounds = new RowBounds((currentPage - 1) * PageSize, PageSize);
List<User> user = session.selectList("com.li.mapper.ResultMapper.selectUserByLimit", null, rowBounds);
for (User user1 : user) {
System.out.println(user1);
}
}
}