MyBatis的简介及HelloWorld程序
MyBatis简介
MyBatis 是一款优秀的半自动化持久化层框架。
MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集的过程。
MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 实体类 【Plain Old Java Objects,普通的 Java对象】映射成数据库中的记录。
MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。
2013年11月迁移到Github。
Mybatis官方文档 : http://www.mybatis.org/mybatis-3/zh/index.html
GitHub : https://github.com/mybatis/mybatis-3
持久化:
持久化是将程序数据在持久状态和瞬时状态间转换的机制。
1.持久化就是将程序中的数据在持久状态(放到数据库中永久保存,只要不删库)和瞬时状态转化的过程。
2.即把数据(如内存中的对象)保存到可永久保存的存储设备中(如磁盘)。持久化的主要应用是将内存中的对象存储在数据库中,或者存储在磁盘文件中、XML数据文件中等等。
3.JDBC就是一种持久化机制。文件IO也是一种持久化机制。
4.生活:冷藏、罐头。
为什么要持久化?
1.有一些对象,不能让它丢掉。
内存:断电即失。不将内存持久化,内存丢失了数据就丢失了,将内存中的数据持久化到对象中。
内存断电后数据会丢失,但有一些对象是无论如何都不能丢失的,比如银行账号等,遗憾的是,人们还无法保证内存永不掉电。
2.内存过于昂贵,与硬盘、光盘等外存相比,内存的价格要高2~3个数量级,而且维持成本也高,至少需要一直供电吧。所以即使对象不需要永久保存,也会因为内存的容量限制不能一直呆在内存中,需要持久化来缓存到外存。
三层架构:
Dao层(持久化层,数据访问层),
Service层(业务层,完成复杂业务操作),
Controller层(接收用户的请求并且把用户的请求转发给下面的Service去做)
持久化是个动词,持久层是个名词。
大多数情况下特别是企业级应用,数据持久化往往也就意味着将内存中的数据保存到磁盘上加以固化,而持久化的实现过程则大多通过各种关系数据库来完成。
为什么要用Mybatis?
1.Mybatis就是帮助程序员将数据存入到数据库中,和从数据库中取数据。
2.传统的jdbc操作 , 有很多重复代码块 .比如 : 数据取出时的封装 , 数据库的建立连接等等... , 通过框架可以减少重复代码,提高开发效率。
3.MyBatis 是一个半自动化的ORM框架 (Object Relationship Mapping) -->对象关系映射。
4.所有的事情,不用Mybatis依旧可以做到,只是用了它,所有实现会更加简单!
技术没有难点,难在复杂业务逻辑处理上。要掌握底层原理像JDBC,可能过几年出新的框架,Mybatis就淘汰了。
优点:去百度百科。
1.简单易学:本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件就可以了,易于学习,易于使用。
2.灵活:Mybatis不会对应用程序或者数据库的现有设计强加任何影响。sql写在xml里,便于统一管理和优化。通过sql语句可以满足操作数据库的所有需求。
3.解除sql与程序代码的耦合:通过提供DAO层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。
4.提供xml标签,支持编写动态sql。
sql和代码的分离,提高了可维护性。
提供映射标签,支持对象与数据库的orm字段关系映射。
提供对象关系映射标签,支持对象关系组建维护。
最重要的一点,使用的人多。后面的SpringBoot等框架就是因为使用的人多所以要不停的学新知识。
可以去MAVEN库站,http://mvnrepository.com 搜索需要的 jar 包的依赖信息,选择使用人数最多的jar包依赖。
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
MyBatis原本是Apache下的一个项目,但是在MyBatis2.0 及 1.0版本的时候,人家不叫MyBatis,而是叫做IBatis,所以以后大家不管是MyBatis还是IBatis,实际上是一回事。是因为在IBatis3.0版本即将推出的时候,
这个团队整体的转战到了谷歌旗下,3.0之后就叫做MyBatis了,MyBatis是一个非常优秀的持久化层的半自动框架。
和我们之前学习的JDBC,DBUtil,JdbcTemplate一样,但是JDBC原生的技术,是Java连接数据库的标准,
DBUtil,JdbcTemplate充其量是一个小工具,不能称之为框架,框架一定是一个整体的解决方案。
先回顾一下原生的JDBC开发的操作步骤:
- 加载数据库驱动程序Class.forName(“驱动类的全类名”);
- 取得数据库连接Connection conn = DirverManager.getConnection(url,root,密码)
- 编写sql
- 数据库操作(增删改用Statement(存在SQL注入,不安全),PreparedStatement, 查询结果集用ResultSet)
- 如果是增删改,且进行多条sql操作,需要进行事务管理(提交或回滚事务)
- 关闭数据库,先用后关,后用先关
JDBC的缺点:
- 代码冗余:相似的代码到处都是
- 功能单一:不能完成缓存操作,不能自动的封装结果集
- 代码耦合度高:所有的sql语句都是写在Java程序中,耦合度高,维护不便
这个时候我们不得不使用工具或者框架,但是工具同样存在以上的问题,所以我们必须使用框架完成持久化层开发,
目标比较流行的框架有:
- Hibernate:是一个非常优秀的全自动框架,Hibernate旨在消除sql,意味着一个不懂sql的人,
也可以使用Hiberate进行数据访问层开发,在开发过程中,完全针对的是实体类的对象,比如创建一个对象,
用save(对象)保存这个对象,这个对象就通过ORM映射关系保存到表中,但是Hibernate存在问题是,
一是不需要编写sql,所以一些复杂的查询由Hibernate自动生成sql,不能进行优化,
二是对于复杂查询来说我们还需要编写另外的一种语句叫做HQL,所以学习成本增加,
三是Hibernate不许程序员编写sql,而是由Hibernate自动的生成sql,所以执行效率比较低。
Hibernate全自动化框架,隐藏了所有的数据库操作(如取得数据库连接,编写sql,执行sql,获取结果集,关闭连接。)
- JAP+SpringData:和Hibernate几乎一样。
- MyBaits:是一个非常优秀的半自动框架,不像Hibernate那样进行隐藏操作,而是将sql的编写交给程序员,
而且sql也不用编写在Java程序中,而是使用xml配置方式(SQL映射文件)编写sql语句,
所以Mybatis的特点:
1.sql与Java代码相分离,使用xml配置方式(SQL映射文件)编写sql语句
2.SQL语句是程序员编写,可以进行更好的优化
3.除了已经学过的sql之前,不会像Hibernate那样学其他的HQL语句。
MyBatis半自动化框架,隐藏了这些操作(取得数据库连接,执行sql,获取结果集,关闭连接。)需要自己编写sql
ORM:Object Relation Mapping 对象关系映射,实际上就是每个实体类都对应上一张表或者视图。
实体类的每个对象就是数据表/视图中的每一笔数据。
Mybatis的HelloWorld程序(非接口式编程,是没有Dao层)
1.创建普通的java Project工程:MyBatis01
2.建个Folder命名为lib,加入jar包,并加载到类路径下,Add Build to Path
mybatis-3.4.1.jar
mysql-connector-java-5.1.37-bin.jar
3.连接数据库中的emp表
4.创建对应的实体类,加上toString方法方便测试
5.为了方便的测试输出MyBatis的日志,加入log4j配置文件和jar包,
log4j.xml和log4j.jar,jar包放lib目录下,log4j配置文件log4j.xml放到src类路径下
(或者new个Source Folder,并命名为conf配置文件类路径,把log4j.xml放到conf目录下)
log4j.xml和log4j.jar不是一定要加的,只是为了方便打印MyBatis的日志。
6.在类路径src下,创建MyBatis的全局配置文件,普通的XML文件(XML File),命名为mybatis.xml
右击项目名new个Source Folder,并命名为conf,此后所有类路径下配置文件放此处。
<?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="mysql"> <!-- 默认使用哪个连接环境ID -->
<environment id="mysql"><!-- 连接环境ID,此处为MYSQL连接 -->
<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/springmvc" />
<property name="username" value="root" />
<property name="password" value="3306" />
</dataSource>
</environment>
<environment id="oracle"><!-- 连接环境ID,此处为ORACLE连接 -->
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="oracle.jdbc.driver.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:@AUTOBVT- CKDOVBK:1521:wanbange" />
<property name="username" value="scott" />
<property name="password" value="3306" />
</dataSource>
</environment>
</environments>
<!-- 注册sql映射文件,一个Dao接口对应一个sql映射文件 -->
<!--在conf目录下建个同名的包com.wanbangee.dao,在此包下建SQL映射文件EmpDao.xml(普通的XML文件)-->
<mappers>
<mapper resource="com/wanbangee/dao/EmpDao.xml" />
</mappers>
<!--resource:这个sql映射文件默认要放在类路径下,conf目录为类路径下的配置文件目录 -->
<!--bin目录是真正的类路径,运行后在项目的工作空间的bin目录会发现src和conf的文件在一起-->
</configuration>
7.编写SQL的映射文件EmpDao.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">
<!-- namespace : 命名空间,此sql映射文件对应的接口全类名,包名加类名 -->
//这里就是sql映射文件EmpDao.xml和EmpDao接口对应
<mapper namespace="com.wanbangee.dao.EmpDao">
<!-- select 标签: 表示的是一个查询的sql
- id 就是标识这条SQL语句的,表示是Dao接口中某一个方法的名称
- resultType 表示这条sql应该返回的值的类型,使用别名或者全类名,建议使用全类名,全类名可按Ctrl加鼠标左击查看类的源代码,别名就点不动了。
- sql中的 #{}表示接受传递参数
-->
<select id="selectEmpByEmpId" resultType="com.wanbangee.entities.Emp">
select emp_id,emp_name,emp_mail,emp_gender,dept_id from emp where emp_id = #{id}
</select>
<select id="selectEmp" resultType="com.wanbangee.entities.Emp">
select * from emp
</select>
//resultType返回值类型,查询的结果集封装成实体类对象的集合,只有查询操作才有resultType返回值类型
//id就是标识这条SQL语句的,一般和接口中的方法名一致,如这里id="selectEmp"是标识select * from emp这条SQL语句的
</mapper>
8.测试,在src下建个com.wanbangee.test包,在包中右击new个JUnit Test Case命名同类名,
如MyBatisTest01,后直接finish,只留一个Test方法,将test()方法命名改为testHelloWorld()
@Test
public void testHelloWorld() throws IOException {
//获取全局配置文件文件的字节输入流
InputStream input = Resources.getResourceAsStream("mybatis.xml");
//创建SqlSessionFactory对象,用来获取SqlSession对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(input);
//获取SqlSession对象,SqlSession表示的是和数据库的一次会话,所以用完必须关闭
SqlSession sqlSession = sqlSessionFactory.openSession();
//根据empId查询有一笔数据,有一个参数empId,返回的是一个对象
Emp emp = sqlSession.selectOne("com.wanbangee.dao.EmpDao.selectEmpByEmpId", 1);
//这个参数是Object类型可以传1,也可以传字符串如"abc",不能指定传入的参数类型是有问题的
//com.wanbangee.dao.EmpDao.selectEmpByEmpId,指定哪条sql语句,全类名加SQL的映射文件名加id名
//查询多笔数据,没有参数,返回的是一个集合
//List<Emp> emps = sqlSession.selectList("com.wanbangee.dao.EmpDao.selectEmp");
//com.wanbangee.dao.EmpDao.selectEmp,指定哪条sql语句,全类名加SQL的映射文件名加id名
System.out.println(emp);
sqlSession.close();//sqlSession表示的是和数据库的一次会话,用完必须关闭
}
查询结果集的数据都为null,因为MyBatis3.4.1 默认的自动驼峰值为false没有开启,需要我们手动开启。
在MyBatis的全局配置文件mybatis.xml中设置自动驼峰命名。
<configuration>
<settings>
<!-- 设置自动驼峰命名 -->
<setting name="mapUnderscoreToCamelCase" value="true"></setting>
</settings>
接口式编程,有Dao层
编写根据empId查询Emp的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">
<mapper namespace="com.wanbangee.dao.EmpDao">
<select id="selectEmpByEmpId" resultType="com.wanbangee.entities.Emp">
select emp_id,emp_name,emp_mail,emp_gender,dept_id from emp where emp_id = #{id}
</select>
</mapper>
@Test
public void testSelectEmpByEmpId() throws Exception {
//获取全局配置文件文件的字节输入流
InputStream input = Resources.getResourceAsStream("mybatis.xml");
//创建SqlSessionFactory对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(input);
//获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//这个参数是Object类型可以传1,也可以传字符串如"abc",不能指定传入的参数类型是有问题的
Emp emp = sqlSession.selectOne("com.wanbangee.dao.EmpDao.selectEmpByEmpId", 1);
//返回的不是一个集合而是一个对象,因为是根据EmpId查询结果是单笔数据
System.out.println(emp);
sqlSession.close();
}
以上的程序,会不会出现问题呢?当然会有问题,没有办法指定传入sql的参数类型,可以随意传递任意类型,
这个参数是Object类型可以传1,也可以传字符串如"abc",不能指定传入的参数类型是有问题的。
所以要加DAO层,在接口里写方法,在方法中指定传入的参数类型。
而且在开发中也存在问题,所谓三层架构,没有DAO层Service层如何调用sql呢?
所以要使用接口式编程:
- 定义数据访问层接口Dao
- 将数据访问层接口Dao和sql映射文件相绑定
- 将数据访问层接口Dao中每个方法的方法名和sql映射文件中的每一条sql语句的id相绑定,即id名就是方法名
- 可以理解SQL映射文件就是DAO的实现类
定义数据访问层接口(这个dao接口要和sql映射文件同包名,接口名和sql映射文件名也要相同)
package com.wanbangee.dao;
import java.util.List;
import com.wanbangee.entities.Emp;
public interface EmpDao {
public List<Emp> selectEmp();//查询全部的
public Emp selectEmpByEmpId(Integer empId);//查询单笔
public void insertEmp(Emp emp);//新增emp
public void deleteEmp(Integer empId);//删除emp
}
定义此接口的sql映射文件, 将数据访问层接口和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">
<mapper namespace="com.wanbangee.dao.EmpDao">
<!-- public List<Emp> selectEmp(); -->
<select id="selectEmp" resultType="com.wanbangee.entities.Emp">
select * from emp
</select>
<!-- public Emp selectEmpByEmpId(Integer empId);-->
<select id="selectEmpByEmpId" resultType="com.wanbangee.entities.Emp">
select * from emp where emp_id = #{empId}
</select>
- 将接口的每个方法和sql映射文件中的每一条sql语句相绑定,方法名要和sql映射文件的sql语句的id相同
select : 表示此方法进行的查询操作,只有查询才有返回值类型resultType
这里的新增和删除方法在接口中都是void没有返回值类型。
id : sql的ID,必须和对应接口中的一个方法名绑定,表示此条sql就是这个方法的sql语句
resultType : 表示这条sql应该返回的值的类型,使用别名或者全类名,建议使用全类名
parameterType : 参数类型,一般情况下,此属性可以省略不写,表示指定传入参数的类型
sql中的#{} 是表示sql以预处理的形式,使用?作为占位符执行sql,
如果传入的参数是一个普通的参数,那么#{索引内容} 就是表中字段名=#{实体类中对应属性}
如果传入的参数为实体类的对象,那么在sql中,必须使用#{实体类JavaBean风格的属性名} 进行参数绑定
<!-- public void insertEmp(Emp emp);-->
<insert id = "insertEmp">
insert into emp(emp_name,emp_mail,emp_gender,dept_id)
values(#{empName},#{empMail},#{empGender},#{deptId})
</insert>
<!-- public void deleteEmp(Integer empId)-->
<delete id="deleteEmp">
delete from emp where emp_id = #{empId}
</delete>
</mapper>
测试:
@Test
public void testEmpQuery() throws Exception {
// 获取全局配置文件文件的字节输入流
InputStream input = Resources.getResourceAsStream("mybatis.xml");
// 创建SqlSessionFactory对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(input);
// 获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//非接口式编程,没有参数
//List<Emp> emps = sqlSession.selectList("com.wanbangee.dao.EmpDao.selectEmp");
// 接口式编程
// 获取接口的实现类对象(通过动态代理完成)
EmpDao empDao = sqlSession.getMapper(EmpDao.class);//获得接口的动态代理实现类
List<Emp> emps = empDao.selectEmp();// 调用接口方法
System.out.println(emps);
sqlSession.close();
}
@Test
public void testSelectEmpByEmpId() throws Exception {
// 获取全局配置文件文件的字节输入流
InputStream input = Resources.getResourceAsStream("mybatis.xml");
// 创建SqlSessionFactory对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(input);
// 获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//非接口式编程,有一个参数empId
// Emp emp = sqlSession.selectOne("com.wanbangee.dao.EmpDao.selectEmpByEmpId", 1);
// 接口式编程
// 获取接口的实现类对象(通过动态代理完成)
EmpDao empDao = sqlSession.getMapper(EmpDao.class);//获得接口的动态代理实现类
Emp emp = empDao.selectEmpByEmpId(1);// 调用接口方法
System.out.println(emp);
sqlSession.close();
}
@Test
public void testInsertEmp() throws Exception {
// 获取全局配置文件文件的字节输入流
InputStream input = Resources.getResourceAsStream("mybatis-conf.xml");
// 创建SqlSessionFactory对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(input);
// 获取SqLSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
// 接口式编程
// 获取接口的实现类对象(通过动态代理完成)
EmpDao empDao = sqlSession.getMapper(EmpDao.class);
Emp emp = new Emp();//调无参构造器,再手动设置属性值进去
emp.setEmpName("AABB");
emp.setEmpMail("aabb@163.com");
// 调用接口方法
empDao.insertEmp(emp);
sqlSession.commit();//提交事务
sqlSession.close();
}
@Test
public void testDeleteEmp() throws Exception {
// 获取全局配置文件文件的字节输入流
InputStream input = Resources.getResourceAsStream("mybatis-conf.xml");
// 创建SqlSessionFactory对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(input);
// 获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
// 接口式编程
// 获取接口的实现类对象(通过动态代理完成)
EmpDao empDao = sqlSession.getMapper(EmpDao.class);
// 调用接口方法
empDao.deleteEmp(11);
sqlSession.commit();//提交事务
sqlSession.close();
}
进行增删改操作,一定要进行事务管理(提交或回滚事务),
不然增删改的数据内容不会持久化 保存到数据库中去,也就是说数据库中数据没有改动。
测试,可以编写Mybatis工具类,便于获取sqlSession对象
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();
}
}
//获取SqlSession连接
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession();
}
}
然后在测试方法中,就可以通过一行代码获得sqlsession对象
SqlSession sqlsession = MybatisUtils.getSqlSession();
以上就是接口式编程,在开发中,实际上也是全部使用接口式编程完成,有很多优点:
- 解耦合,java代码和sql已经分离了,而且数据访问层有实际的接口存在,
整合Spring的时候,就可以将数据访问层加入到IOC容器中管理了。
- 调用方法的时候,参数的类型不能任意了,必须符合接口定义的方法的入参的类型。
总结
1. 接口式编程
原生:Dao----》DaoImpl
MyBatis:Mapper---》xxMapper.xml
2. SqlSession表示的是和数据库的一次会话,所以用完必须关闭
3. SqlSession和Connection一样,都是非线程安全的,所以每次的操作必须重新获取对象。
4. Mapper接口是没有实现类的,但是Mybatis会给这个接口生成一个代理对象(需要将接口和SQL映射文件进行绑定)
5.两个重要的配置文件:
Mybatis的全局配置文件:包含了数据库的连接信息,也可以包含事务管理,系统的运行环境等
sql映射文件:保存了每一条sql语句的映射信息,这个文件就是将sql抽取出来的保存的文件。
sql映射文件可以理解为DAO接口的实现类。
日志工厂
思考:我们在测试SQL的时候,要是能够在控制台输出 SQL 的话,是不是就能够有更快的排错效率?
如果一个 数据库相关的操作出现了问题,我们可以根据输出的SQL语句快速排查问题。
对于以往的开发过程,我们会经常使用到debug模式来调节,跟踪我们的代码执行过程。
但是现在使用Mybatis是基于接口,配置文件的源代码执行过程。因此,我们必须选择日志工具来作为我们开发,调节程序的工具。
Mybatis内置的日志工厂提供日志功能,具体的日志实现有以下几种工具:
SLF4J
Apache Commons Logging
Log4j 2
Log4j
JDK logging
具体选择哪个日志实现工具由MyBatis的内置日志工厂确定。它会使用最先找到的(按上文列举的顺序查找)。
如果一个都未找到,日志功能就会被禁用。
标准日志实现:
指定 MyBatis 应该使用哪个日志记录实现。如果此设置不存在,则会自动发现日志记录实现。
<settings>
<setting name="logImpl" value="LOG4J"/>
</settings>
测试,可以看到控制台有大量的输出!我们可以通过这些输出来判断程序到底哪里出了Bug
Log4j是Apache的一个开源项目,
通过使用Log4j,我们可以控制日志信息输送的目的地:控制台,文本,GUI组件....
我们也可以控制每一条日志的输出格式;
通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。
这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。
导入log4j的包的依赖信息:
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
log4j.xml中的内容:
<?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>