目录
日志
mybatis中实现日志
导入pom
<!-- log start -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.30</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<!-- log end -->
添加logback配置文件
<configuration>
<!--appender 追加器 日志以哪种方式进行输出
name 取个名字
class 不同实现类会输出到不同地方
ch.qos.logback.core.ConsoleAppender 输出到控制台
-->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<!-- 格式 -->
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{100} - %msg%n</pattern>
</encoder>
</appender>
<!--cn.tulingxueyuan.mapper-->
<!--控制跟细粒度的日志级别 根据包\根据类-->
<logger name="cn.tulingxueyuan.mapper" level="debug"></logger>
org.apache.ibatis.transaction
<!--控制所有的日志级别-->
<root level="error">
<!-- 将当前日志级别输出到哪个追加器上面 -->
<appender-ref ref="STDOUT" />
</root>
</configuration>
日志级别
TRACE < DEBUG < INFO < WARN < ERROR
全局配置文件详解
概述
在mybatis的项目中,我们发现了有一个mybatis-config.xml的配置文件,这个配置文件是mybatis的全局配置文件,用来进行相关的全局配置,在任何操作下都生效的配置。下面我们要针对其中的属性做详细的解释,方便大家在后续使用的时候更加熟练。
官方说明:
MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息。 配置文档的顶层结构如下:
- configuration(配置)
- properties(属性)
- settings(设置)
- typeAliases(别名)
- typeHandlers(类型处理器)
- objectFactory(对象工厂)
- plugins(插件)
- environments(环境配置)
- environment(环境变量)
- transactionManager(事务管理器)
- dataSource(数据源)
- environment(环境变量)
- databaseIdProvider(数据库厂商标识)
- mappers(映射器)
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>
<!--引入外部配置文件,类似于Spring中的property-placeholder
resource:从类路径引入
url:从磁盘路径或者网络路径引入
-->
<properties resource="db.properties"></properties>
<!--用来控制mybatis运行时的行为,是mybatis中的重要配置-->
<settings>
<!--设置列名映射的时候是否是驼峰标识-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<!--typeAliases表示为我们引用的实体类起别名,默认情况下我们需要写类的完全限定名
如果在此处做了配置,那么可以直接写类的名称,在type中配置上类的完全限定名,在使用的时候可以忽略大小写
还可以通过alias属性来表示类的别名
-->
<typeAliases>
<!-- <typeAlias type="cn.tulingxueyuan.bean.Emp" alias="Emp"></typeAlias>-->
<!--如果需要引用多个类,那么给每一个类起别名肯定会很麻烦,因此可以指定对应的包名,那么默认用的是类名-->
<package name="cn.tulingxueyuan.bean"/>
</typeAliases>
<!--
在实际的开发过程中,我们可能分为开发环境,生产环境,测试环境等等,每个环境的配置可以是不一样的
environment就用来表示不同环境的细节配置,每一个环境中都需要一个事务管理器以及数据源的配置
我们在后续的项目开发中几乎都是使用spring中配置的数据源和事务管理器来配置,此处不需要研究
-->
<!--default:用来选择需要的环境-->
<environments default="development">
<!--id:表示不同环境的名称-->
<environment id="development">
<transactionManager type="JDBC"/>
<!--配置数据库连接-->
<dataSource type="POOLED">
<!--使用${}来引入外部变量-->
<property name="driver" value="${driverClassname}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<!--
在不同的数据库中,可能sql语句的写法是不一样的,为了增强移植性,可以提供不同数据库的操作实现
在编写不同的sql语句的时候,可以指定databaseId属性来标识当前sql语句可以运行在哪个数据库中
-->
<databaseIdProvider type="DB_VENDOR">
<property name="MySQL" value="mysql"/>
<property name="SQL Server" value="sqlserver"/>
<property name="Oracle" value="orcl"/>
</databaseIdProvider>
<!--将sql的映射文件适用mappers进行映射-->
<mappers>
<!--
指定具体的不同的配置文件
class:直接引入接口的全类名,可以将xml文件放在dao的同级目录下,并且设置相同的文件名称,同时可以使用注解的方式来进行相关的配置
url:可以从磁盘或者网络路径查找sql映射文件
resource:在类路径下寻找sql映射文件
-->
<!-- <mapper resource="EmpDao.xml"/>
<mapper resource="UserDao.xml"/>
<mapper class="cn.tulingxueyuan.dao.EmpDaoAnnotation"></mapper>-->
<!--
当包含多个配置文件或者配置类的时候,可以使用批量注册的功能,也就是引入对应的包,而不是具体的配置文件或者类
但是需要注意的是,
1、如果使用的配置文件的形式,必须要将配置文件跟dao类放在一起,这样才能找到对应的配置文件.
如果是maven的项目的话,还需要添加以下配置,原因是maven在编译的文件的时候只会编译java文件
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
2、将配置文件在resources资源路径下创建跟dao相同的包名
-->
<package name="cn.tulingxueyuan.dao"/>
</mappers>
</configuration>
Mybatis SQL映射文件详解
MyBatis 的真正强大在于它的语句映射,这是它的魔力所在。由于它的异常强大,映射器的 XML 文件就显得相对简单。如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 95% 的代码。MyBatis 致力于减少使用成本,让用户能更专注于 SQL 代码。
SQL 映射文件只有很少的几个顶级元素(按照应被定义的顺序列出):
- cache – 该命名空间的缓存配置。
- cache-ref – 引用其它命名空间的缓存配置。
- resultMap – 描述如何从数据库结果集中加载对象,是最复杂也是最强大的元素。
- parameterMap – 老式风格的参数映射。此元素已被废弃,并可能在将来被移除!请使用行内参数映射。文档中不会介绍此元素。
- sql – 可被其它语句引用的可重用语句块。
- insert – 映射插入语句。
- update – 映射更新语句。
- delete – 映射删除语句。
- select – 映射查询语句。
在每个顶级元素标签中可以添加很多个属性,下面我们开始详细了解下具体的配置。
insert、update、delete元素
属性 | 描述 |
id | 在命名空间中唯一的标识符,可以被用来引用这条语句。 |
parameterType | 将会传入这条语句的参数的类全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过类型处理器(TypeHandler)推断出具体传入语句的参数,默认值为未设置(unset)。 |
parameterMap | 用于引用外部 parameterMap 的属性,目前已被废弃。请使用行内参数映射和 parameterType 属性。 |
flushCache | 将其设置为 true 后,只要语句被调用,都会导致本地缓存和二级缓存被清空,默认值:(对 insert、update 和 delete 语句)true。 |
timeout | 这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为未设置(unset)(依赖数据库驱动)。 |
statementType | 可选 STATEMENT,PREPARED 或 CALLABLE。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED。 |
useGeneratedKeys | (仅适用于 insert 和 update)这会令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键(比如:像 MySQL 和 SQL Server 这样的关系型数据库管理系统的自动递增字段),默认值:false。 |
keyProperty | (仅适用于 insert 和 update)指定能够唯一识别对象的属性,MyBatis 会使用 getGeneratedKeys 的返回值或 insert 语句的 selectKey 子元素设置它的值,默认值:未设置(unset)。如果生成列不止一个,可以用逗号分隔多个属性名称。 |
keyColumn | (仅适用于 insert 和 update)设置生成键值在表中的列名,在某些数据库(像 PostgreSQL)中,当主键列不是表中的第一列的时候,是必须设置的。如果生成列不止一个,可以用逗号分隔多个属性名称。 |
databaseId | 如果配置了数据库厂商标识(databaseIdProvider),MyBatis 会加载所有不带 databaseId 或匹配当前 databaseId 的语句;如果带和不带的语句都有,则不带的会被忽略。 |
<!--如果数据库支持自增可以使用这样的方式-->
<insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
insert into user(user_name) values(#{userName})
</insert>
<!--如果数据库不支持自增的话,那么可以使用如下的方式进行赋值查询-->
<insert id="insertUser2" >
<selectKey order="BEFORE" keyProperty="id" resultType="integer">
select max(id)+1 from user
</selectKey>
insert into user(id,user_name) values(#{id},#{userName})
</insert>
参数的取值方式
在xml文件中编写sql语句的时候有两种取值的方式,分别是#{}和${},下面来看一下他们之间的区别:
<!--获取参数的方式:
1.#{} ==> jdbc String sql=" SELECT id,user_name FROM EMP WHERE id=?"
1.会经过JDBC当中PreparedStatement的预编译,会根据不同的数据类型来编译成对应数据库所对应的数据。
2.能够有效的防止SQL注入。 推荐使用!!
特殊用法:
自带很多内置参数的属性:通常不会使用。了解
javaType、jdbcType、mode、numericScale、resultMap、typeHandler.
比如 需要改变默认的NULL===>OTHER:#{id,javaType=NULL}
想保留小数点后两位:#{id,numericScale=2}
2.${} ==> jdbc String sql=" SELECT id,user_name FROM EMP WHERE id="+id
1.不会进行预编译,会直接将输入进来的数据拼接在SQL中。
2.存在SQL注入的风险。不推荐使用。
特殊用法:
1.调试情况下可以临时使用。
2.实现一些特殊功能:前提一定要保证数据的安全性。
比如:动态表、动态列. 动态SQL.
-->
<select id="SelectEmp" resultType="Emp" resultMap="emp_map" >
SELECT id,user_name,create_date FROM EMP where id=#{id}
</select>
select的参数传递
<!--
参数传递的处理:
1.单个参数:SelectEmp(Integer id);
mybatis 不会做任何特殊要求
获取方式:
#:{输入任何字符获取参数}
2.多个参数:Emp SelectEmp(Integer id,String username);
mybatis 会进行封装
会将传进来的参数封装成map:
1个值就会对应2个map项 : id===> {key:arg0 ,value:id的值},{key:param1 ,value:id的值}
username===> {key:arg1 ,value:id的值},{key:param2 ,value:id的值}
获取方式:
没使用了@Param:
id=====> #{arg0} 或者 #{param1}
username=====> #{arg1} 或者 #{param2}
除了使用这种方式还有别的方式,因为这种方式参数名没有意义:
设置参数的别名:@Param(""):SelectEmp(@Param("id") Integer id,@Param("username") String username);
当使用了@Param:
id=====> #{id} 或者 #{param1}
username=====> #{username} 或者 #{param2}
3. javaBean的参数:
单个参数:Emp SelectEmp(Emp emp);
获取方式:可以直接使用属性名
emp.id=====>#{id}
emp.username=====>#{username}
多个参数:Emp SelectEmp(Integer num,Emp emp);
num===> #{param1} 或者 @Param
emp===> 必须加上对象别名: emp.id===> #{param2.id} 或者 @Param("emp")Emp emp ====>#{emp.id}
emp.username===> #{param2.username} 或者 @Param("emp")Emp emp ====>#{emp.username}
4.集合或者数组参数:
Emp SelectEmp(List<String> usernames);
如果是list,MyBatis会自动封装为map:
{key:"list":value:usernames}
没用@Param("")要获得:usernames.get(0) =====> #{list[0]}
:usernames.get(0) =====> #{agr0[0]}
有@Param("usernames")要获得:usernames.get(0) =====> #{usernames[0]}
:usernames.get(0) =====> #{param1[0]}
如果是数组,MyBatis会自动封装为map:
{key:"array":value:usernames}
没用@Param("")要获得:usernames.get(0) =====> #{array[0]}
:usernames.get(0) =====> #{agr0[0]}
有@Param("usernames")要获得:usernames.get(0) =====> #{usernames[0]}
:usernames.get(0) =====> #{param1[0]}
5.map参数
和javaBean的参数传递是一样。
一般情况下:
请求进来的参数 和pojo对应,就用pojo
请求进来的参数 没有和pojo对应,就用map
请求进来的参数 没有和pojo对应上,但是使用频率很高,就用TO、DTO(就是单独为这些参数创建一个对应的javaBean出来,使参数传递更规范、更重用)
-->
<!--
接口:SelectEmp(String username,@Param("id") Integer id);
username====> #{arg0} #{param1}
id====> #{id} #{param2}
接口:SelectEmp(@Param("beginDate") String beginDate,
String endDate,
Emp emp);
beginDate====> #{beginDate} #{param1}
endDate====> #{arg1} #{param2}
emp.id====>#{arg2.id} #{param2.id}
接口:SelectEmp(List<Integer> ids,
String[] usernames,
@Param("beginDate") String beginDate,
String endDate,);
ids.get(0)=====> #{list[0]} #{param1[0]}
usernames[0]=====> #{array[0]} #{param2[0]}
beginDate====> #{beginDate} #{param3}
end====> #{arg3} #{param4}
-->
处理集合返回结果
EmpDao.xml
<!--当返回值的结果是集合的时候,返回值的类型依然写的是集合中具体的类型-->
<select id="selectAllEmp" resultType="cn.tulingxueyuan.bean.Emp">
select * from emp
</select>
<!--在查询的时候可以设置返回值的类型为map,当mybatis查询完成之后会把列的名称作为key
列的值作为value,转换到map中
-->
<select id="selectEmpByEmpReturnMap" resultType="map">
select * from emp where empno = #{empno}
</select>
<!--注意,当返回的结果是一个集合对象的是,返回值的类型一定要写集合具体value的类型
同时在dao的方法上要添加@MapKey的注解,来设置key是什么结果
@MapKey("empno")
Map<Integer,Emp> getAllEmpReturnMap();-->
<select id="getAllEmpReturnMap" resultType="cn.tulingxueyuan.bean.Emp">
select * from emp
</select>
UserDao.java
public interface EmpDao {
public Emp findEmpByEmpno(Integer empno);
public int updateEmp(Emp emp);
public int deleteEmp(Integer empno);
public int insertEmp(Emp emp);
Emp selectEmpByNoAndName(@Param("empno") Integer empno, @Param("ename") String ename,@Param("t") String tablename);
Emp selectEmpByNoAndName2(Map<String,Object> map);
List<Emp> selectAllEmp();
Map<String,Object> selectEmpByEmpReturnMap(Integer empno);
@MapKey("empno")
Map<Integer,Emp> getAllEmpReturnMap();
}
自定义结果集---resultMap
EmpMapper.xml
<!--1.声明resultMap自定义结果集 resultType 和 resultMap 只能使用一个。
id 唯一标识, 需要和<select 上的resultMap 进行对应
type 需要映射的pojo对象, 可以设置别名
autoMapping 自动映射,(默认=true) 只要字段名和属性名遵循映射规则就可以自动映射,但是不建议,哪怕属性名和字段名一一对应上了也要显示的配置映射
extends 如果多个resultMap有重复映射,可以声明父resultMap,将公共的映射提取出来, 可以减少子resultMap的映射冗余
-->
<resultMap id="emp_map" type="emp" autoMapping="false" extends="common_map">
<result column="create_date" property="cjsj"></result>
</resultMap>
<resultMap id="common_map" type="emp" autoMapping="false" >
<!-- <id> 主键必须使用 对底层存储有性能作用
column 需要映射的数据库字段名
property 需要映射的pojo属性名
-->
<id column="id" property="id"></id>
<result column="user_name" property="username"></result>
</resultMap>
<!--2.使用resultMap 关联 自定义结果集的id-->
<select id="SelectEmp" resultType="Emp" resultMap="emp_map" >
SELECT id,user_name,create_date FROM EMP where id=#{id}
</select>