因为内容太多了,所以将其拆分为以下内容
参考
https://www.bilibili.com/video/BV1NE411Q7Nx
https://mybatis.org/mybatis-3/zh/index.html
日志
日志工厂
logImpl
指定 MyBatis 所用日志的具体实现,未指定时将自动查找。
SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING |
STDOUT_LOGGING | NO_LOGGING
未设置
Mybatis
通过使用内置的日志工厂提供日志功能。内置日志工厂将会把日志工作委托给下面的实现之一:
SLF4J
Apache Commons Logging
Log4j 2
Log4j
JDK logging
配置日志
核心配置加入
1 2 3 <settings > <setting name ="logImpl" value ="STDOUT_LOGGING" /> </settings >
测试结果:
initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 PooledDataSource forcefully closed/removed all connections. PooledDataSource forcefully closed/removed all connections. PooledDataSource forcefully closed/removed all connections. PooledDataSource forcefully closed/removed all connections. Opening JDBC Connection Created connection 1658699134. Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@62ddbd7e] ==> Preparing: select * from user where id = ? ==> Parameters: 1(Integer) <== Columns: id, name, pwd <== Row: 1, 张三, 123456 <== Total: 1 User0{id=1, name='张三', password='123456'} Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@62ddbd7e] Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@62ddbd7e] Returned connection 1658699134 to pool. Process finished with exit code 0
Log4j
Log4j是Apache 的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI 组件,甚至是套接口服务器、NT 的事件记录器、UNIX Syslog 守护进程 等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是,这些可以通过一个配置文件 来灵活地进行配置,而不需要修改应用的代码。
1、导入 log4j 包
1 2 3 4 5 <dependency > <groupId > log4j</groupId > <artifactId > log4j</artifactId > <version > 1.2.17</version > </dependency >
2、log4j.properties
详细配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 log4j.rootLogger =debug,stdout,info,debug,warn,error log4j.appender.stdout =org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout =org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern = [%d{yyyy-MM-dd HH:mm:ss a}]:%p %l%m%n log4j.logger.info =info log4j.appender.info =org.apache.log4j.DailyRollingFileAppender log4j.appender.info.DatePattern ='_'yyyy-MM-dd'.log' log4j.appender.info.File =./src/com/hp/log/info.log log4j.appender.info.Append =true log4j.appender.info.Threshold =INFO log4j.appender.info.layout =org.apache.log4j.PatternLayout log4j.appender.info.layout.ConversionPattern =%d{yyyy-MM-dd HH:mm:ss a} [Thread: %t][ Class:%c >> Method: %l ]%n%p:%m%n log4j.logger.debug =debug log4j.appender.debug =org.apache.log4j.DailyRollingFileAppender log4j.appender.debug.DatePattern ='_'yyyy-MM-dd'.log' log4j.appender.debug.File =./src/com/hp/log/debug.log log4j.appender.debug.Append =true log4j.appender.debug.Threshold =DEBUG log4j.appender.debug.layout =org.apache.log4j.PatternLayout log4j.appender.debug.layout.ConversionPattern =%d{yyyy-MM-dd HH:mm:ss a} [Thread: %t][ Class:%c >> Method: %l ]%n%p:%m%n log4j.logger.warn =warn log4j.appender.warn =org.apache.log4j.DailyRollingFileAppender log4j.appender.warn.DatePattern ='_'yyyy-MM-dd'.log' log4j.appender.warn.File =./src/com/hp/log/warn.log log4j.appender.warn.Append =true log4j.appender.warn.Threshold =WARN log4j.appender.warn.layout =org.apache.log4j.PatternLayout log4j.appender.warn.layout.ConversionPattern =%d{yyyy-MM-dd HH:mm:ss a} [Thread: %t][ Class:%c >> Method: %l ]%n%p:%m%n log4j.logger.error =error log4j.appender.error = org.apache.log4j.DailyRollingFileAppender log4j.appender.error.DatePattern ='_'yyyy-MM-dd'.log' log4j.appender.error.File = ./src/com/hp/log/error.log log4j.appender.error.Append = true log4j.appender.error.Threshold = ERROR log4j.appender.error.layout = org.apache.log4j.PatternLayout log4j.appender.error.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss a} [Thread: %t][ Class:%c >> Method: %l ]%n%p:%m%n
略简版
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 log4j.rootLogger =DEBUG,console,file log4j.appender.console = org.apache.log4j.ConsoleAppender log4j.appender.console.Target = System.out log4j.appender.console.Threshold =DEBUG log4j.appender.console.layout = org.apache.log4j.PatternLayout log4j.appender.console.layout.ConversionPattern =[%c]-%m%n log4j.appender.file = org.apache.log4j.RollingFileAppender log4j.appender.file.File =./log/wnhyang.log log4j.appender.file.MaxFileSize =10mb log4j.appender.file.Threshold =DEBUG log4j.appender.file.layout =org.apache.log4j.PatternLayout log4j.appender.file.layout.ConversionPattern =[%p][%d{yy-MM-dd}][%c]%m%n log4j.logger.org.mybatis =DEBUG log4j.logger.java.sql =DEBUG log4j.logger.java.sql.Statement =DEBUG log4j.logger.java.sql.ResultSet =DEBUG log4j.logger.java.sql.PreparedStatement =DEBUG
极简版
1 2 3 4 5 6 7 8 log4j.rootLogger =ERROR,stdout log4j.logger.org.mybatis.example.BlogMapper =TRACE log4j.appender.stdout =org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout =org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern =%5p [%t] - %m%n
3、配置 log4j
1 2 3 <settings > <setting name ="logImpl" value ="LOG4J" /> </settings >
4、测试运行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 [org.apache.ibatis.logging.LogFactory]-Logging initialized using 'class org.apache.ibatis.logging.log4j.Log4jImpl' adapter. [org.apache.ibatis.datasource.pooled.PooledDataSource]-PooledDataSource forcefully closed/removed all connections. [org.apache.ibatis.datasource.pooled.PooledDataSource]-PooledDataSource forcefully closed/removed all connections. [org.apache.ibatis.datasource.pooled.PooledDataSource]-PooledDataSource forcefully closed/removed all connections. [org.apache.ibatis.datasource.pooled.PooledDataSource]-PooledDataSource forcefully closed/removed all connections. [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-Opening JDBC Connection [org.apache.ibatis.datasource.pooled.PooledDataSource]-Created connection 279593458. [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@10aa41f2] [com.dao.UserMapper.getUserById]-==> Preparing: select * from user where id = ? [com.dao.UserMapper.getUserById]-==> Parameters: 1(Integer) [com.dao.UserMapper.getUserById]-<== Total: 1 User0{id=1, name='张三', password='123456'} [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@10aa41f2] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@10aa41f2] [org.apache.ibatis.datasource.pooled.PooledDataSource]-Returned connection 279593458 to pool.
简单使用:
1、在要使用 Log4j 的类中,导入包
import org.apache.log4j.Logger;
2、日志对象,参数为当前的class
1 static Logger logger= Logger.getLogger(UserDaoTest.class);
3、日志级别
1 2 3 logger.info("info:进入了testLog4j" ); logger.debug("debug:进入了testLog4j" ); logger.error("error:进入了testLog4j" );
注解开发
使用注解来映射简单语句会使代码显得更加简洁,但对于稍微复杂一点的语句,Java
注解不仅力不从心,还会让你本就复杂的 SQL 语句更加混乱不堪。
因此,如果你需要做一些很复杂的操作,最好用 XML 来映射语句。
1、接口方法上加上注解
1 2 @Select("select * from user") List<User> getUserList () ;
2、核心配置绑定接口
1 2 3 <mappers > <mapper resource ="com/dao/UserMapper.class" /> </mappers >
xml 与注解同时使用需要:接口和它的 Mapper
配置文件必须同名且必须在同一包下,并配置 xml
3、测试
本质:反射机制实现
底层:动态代理
CRUD
1 2 3 4 5 6 7 8 @Select() ... @Insert() ... @Update() .... @Delete() ...
关于 @Param () 注解
8基本类型 + String 类型,需要加上
引用类型不用加
只有一个基本类型,可以忽略,但建议加上
在 sql 中引用的就是我们这里的 @Param () 中设定的属性名
#{} ${} 区别
参考:
MyBatis视频教程
[#{}与\({}的区别](https://blog.csdn.net/qian_qian_123/article/details/92844194?ops_request_misc=%25257B%252522request%25255Fid%252522%25253A%252522160759025519726885835134%252522%25252C%252522scm%252522%25253A%25252220140713.130102334..%252522%25257D&request_id=160759025519726885835134&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~baidu_landing_v2~default-3-92844194.pc_search_result_no_baidu_js&utm_term=#{}%E4%B8%8E\) {}%E5%8C%BA%E5%88%AB)
Mybatis 详细执行流程
参考
复杂查询
数据库准备
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 CREATE TABLE `teacher` ( `id` INT (10 ) NOT NULL , `name` VARCHAR (30 ) DEFAULT NULL , PRIMARY KEY (`id`) ) ENGINE= INNODB DEFAULT CHARSET= utf8 INSERT INTO teacher(`id`, `name`) VALUES (1 , '老杨' ); CREATE TABLE `student` ( `id` INT (10 ) NOT NULL , `name` VARCHAR (30 ) DEFAULT NULL , `tid` INT (10 ) DEFAULT NULL , PRIMARY KEY (`id`), KEY `fktid` (`tid`), CONSTRAINT `fktid` FOREIGN KEY (`tid`) REFERENCES `teacher` (`id`) ) ENGINE= INNODB DEFAULT CHARSET= utf8 INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('1' , '小明' , '1' ); INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('2' , '小红' , '1' ); INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('3' , '小张' , '1' ); INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('4' , '小李' , '1' ); INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('5' , '小王' , '1' );
配置
实体类(使用了 Lombok 插件)
Teacher
1 2 3 4 5 6 7 @Data @NoArgsConstructor @AllArgsConstructor public class Teacher { private int id; private String name; }
Student
1 2 3 4 5 6 7 8 @Data @NoArgsConstructor @AllArgsConstructor public class Student { private int id; private String name; private Teacher teacher; }
接口和对应的 Mapper.xml
注意放在同一包下,且命名相同,如下模板
1 2 3 4 5 6 7 8 <?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.dao.xxxMapper" > </mapper >
核心配置
如果需要的话修改 db.properties
mybatis-config.xml 修改
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 <?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 > <properties resource ="db.properties" /> <settings > <setting name ="logImpl" value ="STDOUT_LOGGING" /> </settings > <typeAliases > <package name ="com.pojo" /> </typeAliases > <environments default ="development" > <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 > </environments > <mappers > <mapper resource ="com/dao/UserMapper.xml" /> <mapper resource ="com/dao/TeacherMapper.xml" /> <mapper resource ="com/dao/StudentMapper.xml" /> </mappers > </configuration >
测试
要求一:
查询所有学生信息,内容包括(学生id,学生name,老师name)
方法一:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <resultMap id ="studentMap" type ="Student" > <result column ="id" property ="id" /> <result column ="name" property ="name" /> <association property ="teacher" column ="tid" javaType ="teacher" select ="getTeacherById" /> </resultMap > <select id ="getStudent" resultMap ="studentMap" > select * from student </select > <select id ="getTeacherById" resultType ="teacher" > select * from teacher where id = #{id} </select >
按照查询嵌套处理,相当于子查询
方法二:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <resultMap id ="studentMap0" type ="Student" > <result column ="sid" property ="id" /> <result column ="sname" property ="name" /> <association property ="teacher" javaType ="teacher" > <result column ="tname" property ="name" /> </association > </resultMap > <select id ="getStudent0" resultMap ="studentMap0" > select s.id sid, s.name sname, t.name tname from student s, teacher t where s.tid = t.id </select >
按照结果嵌套处理,即连表查询
要求二:
查询所有老师信息,内容包括(老师id,老师name,所有学生(学生id,学生name,学生老师id))
实体类的变化
Student0
1 2 3 4 5 6 7 8 @Data @NoArgsConstructor @AllArgsConstructor public class Student0 { private int id; private String name; private int tid; }
Teacher0
1 2 3 4 5 6 7 8 @Data @NoArgsConstructor @AllArgsConstructor public class Teacher0 { private int id; private String name; private List<Student0> student0s; }
方法一:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <resultMap id ="teacherMap0" type ="teacher0" > <result column ="id" property ="id" /> <result column ="name" property ="name" /> <collection property ="student0s" javaType ="ArrayList" ofType ="Student0" select ="getStudentByTid" column ="id" /> </resultMap > <select id ="getTeacher0" resultMap ="teacherMap0" > select * from teacher where id = #{id} </select > <select id ="getStudentByTid" resultType ="student0" > select * from student where tid = #{id} </select >
按照查询嵌套处理,相当于子查询
方法二:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <resultMap id="teacherMap" type="teacher0" > <result column="tid" property="id" /> <result column="tname" property="name" /> <!-- javaType="" 指定属性类型 集合中的泛型信息,我们使用 ofType 获取 --> <collection property="student0s" ofType="Student0" > <result property="id" column="sid" /> <result property="name" column="sname" /> <result property="tid" column="tid" /> </collection> </resultMap> <select id="getTeacher" resultMap="teacherMap" > select t.id tid, t.name tname, s.id sid, s.name sname from student s, teacher t where s.tid = t.id and t.id = #{id} </select>
按照结果嵌套处理,即连表查询
总结
1、关联 - association
2、集合 - collection
3、javaType & ofType
javaType 用来指定实体类中属性的类型
ofType 用来指定映射到 List 或集合中的 pojo
类型,泛型中的约束类型
注意点:
sql 可读性
数据库字段与实体类属性对应
排错依靠日志信息(log4j等)
因为内容太多了,所以将其拆分为以下内容