1.Mybatis简介
2.入门案例
3.详细解释
一、Mybatis简介
MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。
iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAOs)
当前,最新版本是MyBatis 3.5.3 ,其发布时间是2019年10月20日。
二、入门案例
目录结构
1、数据库
2、pom.xml
<?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.xj</groupId>
<artifactId>Mybatis</artifactId>
<version>1.0.0</version>
<dependencies>
<!--mybatis依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<!--mysql连接驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
<!--Junit单元测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.20</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
3、主配置文件 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>
<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://127.0.0.1:3306/Mybatis"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!--关联映射文件-->
<!--resource可以直接写文件的全限名,从classes文件中寻找文件-->
<mappers>
<mapper resource="com/xj/dao/UserMapper.xml"></mapper>
</mappers>
</configuration>
4、实体类User
package com.xj.bean;
import lombok.*;
import java.math.BigDecimal;
import java.util.Date;
/**
* Created by Administrator on 2019/12/20 0020.
*/
@Getter@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class User {
private Integer id;
private String name;
private String password;
private Integer age;
private Date birthday;
private BigDecimal salary;
}
5、工具类 MyBatisUtils
package com.xj.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;
/**
* Created by Administrator on 2019/12/20 0020.
*/
public class MyBatisUtils {
private static SqlSessionFactory factory = null;
static{
//加载主配置文件
String resource = "Mybatis-config.xml";
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream(resource);
} catch (IOException e) {
e.printStackTrace();
}
factory = new SqlSessionFactoryBuilder().build(inputStream);
}
//获取session对象
public static SqlSession getSession(){
return factory.openSession();
}
}
6、dao
package com.xj.dao;
import com.xj.bean.User;
import java.util.List;
/**
* Created by Administrator on 2019/12/20 0020.
*/
public interface IUserDao {
void save (User user);
void update(User user);
void delete(Integer id);
User get(Integer id);
List<User> list();
}
package com.xj.dao.impl;
import com.xj.bean.User;
import com.xj.dao.IUserDao;
import com.xj.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import java.util.List;
/**
* Created by Administrator on 2019/12/20 0020.
*/
public class UserDaoImpl implements IUserDao {
//执行保存的操作
public void save(User user) {
//获取SqlSession对象
SqlSession session = MyBatisUtils.getSession();
//执行保存的sql语句
session.insert("com.xj.dao.IUserDao.save",user);//第一个参数为映射文件的namespace值+id值
//提交事务
session.commit();
session.close();
}
//执行更新的操作
public void update(User user) {
SqlSession session = MyBatisUtils.getSession();
session.update("com.xj.dao.IUserDao.update",user);
session.commit();
session.close();
}
//执行删除的操作
public void delete(Integer id) {
SqlSession session = MyBatisUtils.getSession();
session.delete("com.xj.dao.IUserDao.delete",id);
session.commit();
session.close();
}
//根据id查询
public User get(Integer id) {
SqlSession session = MyBatisUtils.getSession();
User user = session.selectOne("com.xj.dao.IUserDao.get",id);
return user;
}
//查询全部
public List<User> list() {
SqlSession session = MyBatisUtils.getSession();
List<User> list = session.selectList("com.xj.dao.IUserDao.list");
return list;
}
}
7、映射文件 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">
<!--映射文件通常和dao接口放在同一个包中-->
<!--namespace的命名规范,通常为接口的全限名-->
<mapper namespace="com.xj.dao.IUserDao">
<insert id="save">
insert into user (name,password,age,birthday,salary)
values (#{name},#{password},#{age},#{birthday},#{salary})/*调用get方法*/
</insert>
<update id="update">
update user
set
name = #{name},
password = #{password},
age = #{age},
birthday = #{birthday},
salary = #{salary}
where
id = #{id}
</update>
<delete id="delete">
delete from user where id = #{id}/*获取参数的值,并不是调用get方法*/
</delete>
<select id="get" resultType="com.xj.bean.User">/*查询的时候必须要有返回值类型,这返回的是类的全限定名*/
select id,name,password,age,birthday,salary from user where id = #{id}
</select>
<select id="list" resultType="com.xj.bean.User">/*如果返回的是集合,那应该是设置为集合包含的类型*/
select id,name,password,age,birthday,salary from user
</select>
</mapper>
8、测试类
import com.xj.bean.User;
import com.xj.dao.IUserDao;
import com.xj.dao.impl.UserDaoImpl;
import org.junit.Test;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
/**
* Created by Administrator on 2019/12/20 0020.
*/
public class MybatisTest{
@Test
public void testSave() throws Exception{
IUserDao dao = new UserDaoImpl();
User user = new User(null,"jack","222",23,new Date(),new BigDecimal(2000));
dao.save(user);
}
@Test
public void testUpdate() throws Exception{
IUserDao dao = new UserDaoImpl();
User user = new User(2,"rose","222",44,new Date(),new BigDecimal(3000));
dao.update(user);
}
@Test
public void testDelete() throws Exception{
IUserDao dao = new UserDaoImpl();
dao.delete(2);
}
@Test
public void testGet() throws Exception{
IUserDao dao = new UserDaoImpl();
User user = dao.get(1);
System.out.println(user);
}
@Test
public void testList() throws Exception{
IUserDao dao = new UserDaoImpl();
List<User> list = dao.list();
System.out.println(list);
}
}
三、详细解释
1.主配置文件
(1)环境配置(environments)
MyBatis 可以配置成适应多种环境,这种机制有助于将 SQL 映射应用于多种数据库之中。
注:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。所以,如果你想连接两个数据库,就需要创建两个 SqlSessionFactory 实例,每个数据库对应一个。而如果是三个数据库,就需要三个实例
为了指定创建哪种环境,只要将它作为可选的参数传递给 SqlSessionFactoryBuilder 即可。可以接受环境配置的两个方法签名是:
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment, properties);
如果忽略了环境参数,那么默认环境将会被加载,如下所示:
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, properties);
环境元素定义了如何配置环境。
1、默认使用的环境 ID(比如:default="development")。
2、每个 environment 元素定义的环境 ID(比如:id="development")。
3、事务管理器的配置(比如:type="JDBC")。
4、数据源的配置(比如:type="POOLED")。
5、默认的环境和环境 ID 是自解释的,因此一目了然。 你可以对环境随意命名,但一定要保证默认的环境 ID 要匹配其中一个环境 ID。
1)事务管理器(transactionManager)
在 MyBatis 中有两种类型的事务管理器(也就是 type=”[JDBC|MANAGED]”):
JDBC – 这个配置就是直接使用了 JDBC 的提交和回滚设置,它依赖于从数据源得到的连接来管理事务作用域。
MANAGED – 这个配置几乎没做什么。它从来不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。 默认情况下它会关闭连接,然而一些容器并不希望这样,因此需要将 closeConnection 属性设置为 false 来阻止它默认的关闭行为。例如:
<transactionManager type="MANAGED">
<property name="closeConnection" value="false"/>
</transactionManager>
2)数据源(dataSource)
dataSource 元素使用标准的 JDBC 数据源接口来配置 JDBC 连接对象的资源。
有三种内建的数据源类型(也就是 type=”[UNPOOLED|POOLED|JNDI]”):
UNPOOLED– 这个数据源的实现只是每次被请求时打开和关闭连接。虽然有点慢,但对于在数据库连接可用性方面没有太高要求的简单应用程序来说,是一个很好的选择。 不同的数据库在性能方面的表现也是不一样的,对于某些数据库来说,使用连接池并不重要,这个配置就很适合这种情形。
POOLED– 这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来,避免了创建新的连接实例时所必需的初始化和认证时间。 这是一种使得并发 Web 应用快速响应请求的流行处理方式。
JNDI – 这个数据源的实现是为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的引用。
3)映射器(mappers)
定义 了SQL 映射语句,我们需要告诉 MyBatis 到哪里去找到这些语句。 Java 在自动查找这方面没有提供一个很好的方法,所以最佳的方式是告诉 MyBatis 到哪里去找映射文件。 你可以使用相对于类路径的资源引用, 或完全限定资源定位符(包括 file:/// 的 URL),或类名和包名等。例如:
<!-- 使用相对于类路径的资源引用 -->
<mappers>
<mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
<mapper resource="org/mybatis/builder/BlogMapper.xml"/>
<mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>
<!-- 使用完全限定资源定位符(URL) -->
<mappers>
<mapper url="file:///var/mappers/AuthorMapper.xml"/>
<mapper url="file:///var/mappers/BlogMapper.xml"/>
<mapper url="file:///var/mappers/PostMapper.xml"/>
</mappers>
<!-- 使用映射器接口实现类的完全限定类名 -->
<mappers>
<mapper class="org.mybatis.builder.AuthorMapper"/>
<mapper class="org.mybatis.builder.BlogMapper"/>
<mapper class="org.mybatis.builder.PostMapper"/>
</mappers>
<!-- 将包内的映射器接口实现全部注册为映射器 -->
<mappers>
<package name="org.mybatis.builder"/>
</mappers>
2.关联属性文件
如果直接在主文件中配置了这些值,项目上线以后,就不容易更改,可以添加一个关联属性文件文件db.properies,来实现动态配置。
3.配置别名
类型别名是为 Java 类型设置一个短的名字。 它只和 XML 配置有关,存在的意义仅在于用来减少类完全限定名的冗余。
注:在主文件中配置别名。且位置不能在上个例子属性配置之前。
(1)为单个类配置别名
(2)给配置的包下的所有java类配置别名
如果需要配置别名的java类比较多,上面配置别名的方法会很麻烦,因此可以直接指定一个包名,该包下的所有java类都可以使用别名。(默认情况下,别名为类名且大小写不敏感)
(3)使用注解显式的写别名
上面第二种指定包名,因为存在大小写不敏感的问题,如果一个包下的类名不区分大小写,例如,存在user类和USER类,那么写的别名就不会指想要指定的那个类,
解决办法,在每个java类中使用注解的方式显示的定义别名
4.保存自动生成的主键
parameterType | 将会传入这条语句的参数类的完全限定名或别名。(可以省略) |
useGeneratedKeys | (仅对 insert 和 update 有用)这会令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键(比如:像 MySQL 和 SQL Server 这样的关系数据库管理系统的自动递增字段),默认值:false。 |
keyProperty | (仅对 insert 和 update 有用)唯一标记一个属性,MyBatis 会通过 getGeneratedKeys 的返回值或者通过 insert 语句的 selectKey 子元素设置它的键值,默认值:未设置(unset)。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。 |
keyColumn | (仅对 insert 和 update 有用)通过生成的键值设置表中的列名,这个设置仅在某些数据库(像 PostgreSQL)是必须的,当主键列不是表中的第一列的时候需要设置。如果希望使用多个生成的列,也可以设置为逗号分隔的属性名称列表。 |
5.结果映射
数据中查询出来的结果集,根据同名匹配原则(属性名和列名一致)进行封装,赋值给User对象,但是User属性中,是没有u_id,u_name,u_password等这些属性。
解决方法一:起别名
解决方法二:使用结果集映射标签ResultMap(添加在映射文件中)
id和result的差别:
相同点:id 和 result 元素都将一个列的值映射到一个简单数据类型(String, int, double, Date 等)的属性或字段。
不同点:id 元素表示的结果将是对象的标识属性(主键),这会在比较对象实例时用到。 这样可以提高整体的性能,尤其是进行缓存和嵌套结果映射(也就是连接映射)的时候。
resultMap和resultType的差别:
相同点:两者都是表示查询结果集与java对象之间的一种关系,处理查询结果集映射到java对象。
不同点:resultMap:表示将查询结果集中的列一一映射到bean对象的各个属性。ResultType:表示的是bean中的对象类,此时可以省略掉resultMap标签的映射,但是必须保证查询结果集中的属性 和 bean对象类中的属性是一一对应的,此时大小写不敏感,但是有限制。
6.日志框架
日志配置
步骤 1:添加 Log4J 的 jar 包
<!--log4j日志-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
步骤 2:配置 Log4J
在应用的类路径中创建一个名称为 log4j.properties 的文件,文件的具体内容如下:
# Global logging configuration
log4j.rootLogger=ERROR, stdout
# MyBatis logging configuration...
log4j.logger.com.xj.dao.IUserDao=TRACE
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
日志级别:log4j定义了8个级别的log(除去OFF和ALL,可以说分为6个级别),优先级从高到低依次为:OFF、FATAL、ERROR、WARN、INFO、DEBUG、TRACE、 ALL。
ALL 最低等级的,用于打开所有日志记录。
TRACE designates finer-grained informational events than the DEBUG.Since:1.2.12,很低的日志级别,一般不会使用。
DEBUG 指出细粒度信息事件对调试应用程序是非常有帮助的,主要用于开发过程中打印一些运行信息。
INFO 消息在粗粒度级别上突出强调应用程序的运行过程。打印一些你感兴趣的或者重要的信息,这个可以用于生产环境中输出程序运行的一些重要信息,但是不能滥用,避免打印过多的日志。
WARN 表明会出现潜在错误的情形,有些信息不是错误信息,但是也要给程序员的一些提示。
ERROR 指出虽然发生错误事件,但仍然不影响系统的继续运行。打印错误和异常信息,如果不想输出太多的日志,可以使用这个级别。
FATAL 指出每个严重的错误事件将会导致应用程序的退出。这个级别比较高了。重大错误,这种级别你可以直接停止程序了。
OFF 最高等级的,用于关闭所有日志记录。
如果将log level设置在某一个级别上,那么比此级别优先级高的log都能打印出来。例如,如果设置优先级为WARN,那么OFF、FATAL、ERROR、WARN 4个级别的log能正常输出,而INFO、DEBUG、TRACE、 ALL级别的log则会被忽略。Log4j建议只使用四个级别,优先级从高到低分别是ERROR、WARN、INFO、DEBUG。