MyBatis 3
MyBatis 3 学习笔记
一、Mybatis 基础知识
1.MyBatis 3编写步骤:
- 根据mybatis-config.xml配置文件创建一个SqlSessionFactory对象。
- sql映射文件,配置了每一个sql,以及sql的封装规则
- 将sql映射文件注册到全局配置文件mybatis-config.xml中
- 写代码:
- 根据全局配置文件得到SqlSessionFactory
- 从SqlSessionFactory中获取SqlSession对象,使用它来做增删改查。一个SqlSession就代表和数据额 库的一次会话,用完要关闭
- 使用sql标识来告诉mybatis执行那个sql。sql都是保存在SQL映射文件中的。
mybatis-config.xml 文件 <!-- 将我们写好的sql映射文件(EmployeeMapper.xml)一定要注册到全局配置文件(mybatis-config.xml)中 --> <mappers> <mapper resource="EmployeeMapper.xml" /> </mappers> </configuration>
//1.通过配置文件创建一个sqlSessionFactory String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //2.获取SqlSession实例,能直接执行已经映射的SQL语句 SqlSession openSession = sqlSessionFactory.openSession(); //3.参数一:statement唯一标识,参数二:传入sql变量 try { Employee employee = openSession.selectOne("cn.guet.bean.EmployeeMapper.selectEmployee", 1); System.out.println(employee); }catch (Exception e){ e.printStackTrace(); }finally { openSession.close(); }
SQL映射文件: <mapper namespace="cn.guet.bean.EmployeeMapper"> <!-- namespace:名称空间;指定为接口的全类名 id:唯一标识 resultType:返回值类型 #{id}:从传递过来的参数中取出id值 public Employee getEmpById(Integer id); --> <select id="selectEmployee" resultType="cn.guet.bean.Employee"> select id,last_name lastName,email,gender from tb1_employee where id = #{id} </select> </mapper>
2.MyBatis 3 接口式编程中,在进行接口和SQL的动态绑定时,SQL映射文件中的namespace指定为mapper接口的全限定名,映射文件中的id 指定为接口的中方法。动态绑定以后,不用再写mapper的实现类。mybatis会为我们自动创建一个代理对象,代理对象去执行增删改查的方法。
3.接口式编程: 原生 Dao ==> DaoImpl; mybatis: Mapper ==> xxxMapper.xml
4.Configuration,全局配置文件mybatis-config.xml 的标签 (p.s. 标签有顺序)
- properties标签,用来引入 jdbc文件。
<!--配置数据源信息-->
<properties resource="jdbc.properties"></properties>
- settings设置标签,用来设置各种信息。如下划线转驼峰标识。
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
- typeAliases别名标签。mybatis中的别名处理器。给Java type 一个短一点简单一点的别名,以后xml文件引用式直接用别名。
<!--typeAliases别名处理器,可以为Java类型取别名-->
<typeAliases>
<!--typeAlias为某个Java类型取别名。默认别名是类名小写employee-->
<!--<typeAlias type="cn.guet.bean.Employee" alias="emp"></typeAlias>-->
<!--批量取别名-->
<!--package为某个包下的所有类型批量起别名,name指定报名,为包以及包下面的所有类起默认别名(类名小写)-->
<package name="cn.guet.bean"/>
</typeAliases>
当使用批量起别名,且包里面有类名重复是,可以使用@Alias("xxx")指定别名
@Alias("emp")
public class Employee {
private Integer id;
private String lastName;
- typeHandlers类型处理器标签。Java类型和数据库类型映射的桥梁。
- plugins插件标签。插件可以拦截以下四大对象。
• Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
• ParameterHandler (getParameterObject, setParameters)
• ResultSetHandler (handleResultSets, handleOutputParameters)
• StatementHandler (prepare, parameterize, batch, update, query)
- mappers标签。将sql映射注册到全局配置文件中。
<!--
mappers:注册一个sql映射文件,
resource:引用类路径下的映射文件,
url:引用磁盘路径下的映射文件,
class:引用注册接口,
1.有SQL文件,映射文件名必须和接口同名,并且放在与接口同一目录下。
2.没有SQL文件,所有的SQL都是利用注解写在接口上。
推荐:比较重要的,复杂的Dao接口写映射文件,不重要的、简单的可以写注解
-->
<mappers>
<!--<mapper class="cn.guet.dao.EmployeeMapperAnnotation"/>-->
<!--<mapper resource="EmployeeMapper.xml" />-->
<!-- <mapper url="file:///var/mappers/AuthorMapper.xml"/>-->
<!--批量注册-->
<package name="cn.guet.dao"/>
</mappers>
/**
* 基于注解版的Mapper接口
*/
public interface EmployeeMapperAnnotation {
@Select("select id,last_name ,email,gender from tb1_employee where id = #{id}")
public Employee getEmployeeById(Integer id);
}
<!--
p.s. mybatis错误——java.io.IOException: Could not find resource com/xxx/xxxMapper.xml
原因:IDEA是不会编译src的java目录的xml文件,所以在Mybatis的配置文件中找不到xml文件!(也有可能是Maven构建项目的问题,网上教程很多项目是普通的Java web项目,所以可以放到src下面也能读取到)
在Maven的pom文件中,添加下面代码:
-->
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
5.Mapper XML Files 中的 select、insert、update and delete 不做过多的赘述。
6.参数的处理
- 单个参数:mybatis不会做特殊处理,#{参数名/任意名}:取出参数值。
- 多个参数:mybatis会做特殊处理。多个参数会被封装成 一个map,key:param1...paramN,或者参数的索引也可以,value:传入的参数值,#{}就是从map中获取指定的key的值。
- 异常:org.apache.ibatis.binding.BindingException: Parameter 'id' not found. Available parameters are [1, 0, param1, param2]。操作:
- 方法:public Employee getEmpByIdAndLastName(Integer id,String lastName);
- 取值:#{id},#{lastName}
- 命名参数:明确指定封装参数时map的key;@Param("id"),多个参数会被封装成 一个map。key:使用@Param注解指定的值,value:参数值。#{指定的key}取出对应的参数值。
- POJO:如果多个参数正好是我们业务逻辑的数据模型,我们就可以直接传入pojo;#{属性名}:取出传入的pojo的属性值。
- Map:如果多个参数不是业务模型中的数据,没有对应的pojo,不经常使用,为了方便,我们也可以传入map,#{key}:取出map中对应的值。
- 总结:参数多时会封装map,为了不混乱,我们可以使用@Param来指定封装时使用的key;#{key}就可以取出map中的值。
/*mybatis处理参数源代码 */
org.apache.ibatis.reflection.ParamNameResolver
7.${xxx} 与 #{xxx} 区别:
#{}:是以预编译的形式,将参数设置到sql语句中;PreparedStatement;防止sql注入。${}:取出的值直接拼装在sql语句中;会有安全问题;大多情况下,我们去参数的值都应该去使用#{}。原生jdbc不支持占位符的地方我们就可以使用${}进行取值。比如分表、排序;按照年份分表拆分select * from ${year}_salary where xxx。select * from tbl_employee order by ${f_name} ${order}
8.select 查询返回一个list时,resultType=pojo类型。
<select id="findEmployeeByLastName" resultType="cn.guet.bean.Employee">
select *from tb1_employee where last_name like #{lastName}
</select>
9.Dynamic SQL
- if 条件判断,条件成立时,则拼接SQL。
<select id="getEmpsByConditionIf" resultType="cn.guet.bean.Employee">
select *from tb1_employee
<where>
<if test="id!=null">
id=#{id}
</if>
<if test="lastName!=null && lastName!=""">
and last_name like #{lastName}
</if>
</where>
</select>
- choose (when, otherwise) 当条件成立,则拼接SQL,只会拼接一个SQL。
<select id="getEmpsByConditionChoose" resultType="cn.guet.bean.Employee">
select *from tb1_employee
<where>
<!--如果带了id,就用id查。如果带了lastname就用lastname查询-->
<choose>
<when test="id!=mull">
id = #{id}
</when>
<when test="lastName!=null">
last_name like #{lastName}
</when>
<otherwise>
gender = "1"
</otherwise>
</choose>
</where>
</select>
- trim (where, set) 可以实现部分数据更新
<update id="updateEmployee">
update tb1_employee
<trim prefix="SET" suffixOverrides=",">
<if test="lastName!=null && lastName!=""">last_name=#{lastName},</if>
<if test="email!= null">email=#{email},</if>
<if test="gender!= null">gender=#{gender},</if>
</trim>
where id=#{id}
</update>
- foreach 个人感觉意义不大,略。
10.SQL片段抽取
<sql id="select_column">
<where>
<if test="id!=null">
id=#{id}
</if>
<if test="lastName!=null && lastName!=""">
and last_name like #{lastName}
</if>
</where>
</sql>
<select id="getEmpsByConditionIf" resultType="cn.guet.bean.Employee">
select *from tb1_employee
<include refid="select_column"></include>
</select>
二、Mybatis 缓存机制 (未完、、、)
1.mybatis提供两级缓存
- 一级缓存(本地缓存):sqlSession级别的缓存,一直开启,无法关闭。就是与数据库一次会话期间查询到的数据会放在本地缓存中。以后如果需要获取相同的数据,直接从缓存中拿,没必要再去查询数据库。一级缓存就是sqlSession级别的一个map,一级缓存失效的情况(失效了即要重新查询):
- sqlSession不同。
- sqlSession相同,查询条件不同.(当前一级缓存中还没有这个数据)
- sqlSession相同,两次查询之间执行了增删改操作(这次增删改可能对当前数据有影响)
- sqlSession相同,手动清除了一级缓存(缓存清空)
- 二级缓存(全局缓存):是namespace级别的缓存,一个namespace对应一个二级缓存。
- 工作机制:
- 一个会话,查询一条数据,这个数据就会被放在当前会话的一级缓存中;
- 如果会话关闭;一级缓存中的数据会被保存到二级缓存中;新的会话查询信息,就可以参照二级缓存中的内容;
- sqlSession===EmployeeMapper==>Employee;DepartmentMapper===>Department。不同namespace查出的数据会放在自己对应的缓存中(map)。查出的数据都会被默认先放在一级缓存中。只有会话提交或者关闭以后,一级缓存中的数据才会转移到二级缓存中
- 工作机制:
三、Mybatis 和 Spring整合
1.创建maven创建web-app工程,然后添加依赖。需要添加的依赖有 spring (4.0.9)、springmvc、mybatis(1.3.0)、mybatis-spring、mysql-connector-java、c3p0、taglibs、log4j。pom文件中注意以后下代码:
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
<directory>${basedir}/src/main/resources</directory>
</resource>
</resources>
2.配置web.xml
<!--Spring配置: needed for ContextLoaderListener -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- SpringMVC配置 -->
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
3.配置SpringMVC,springmvc默认会加载WEB-INF/spring-servlet.xml文件,配置如下:
<!--SpringMVC只是控制网站跳转逻辑 -->
<!-- 只扫描控制器 -->
<context:component-scan base-package="cn.guet.controller" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!-- 视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<mvc:annotation-driven></mvc:annotation-driven>
<mvc:default-servlet-handler/>
4.到这里springmvc 应该是可以工作了,应该写一个controller,测试springmvc是否正常。
5.配置mybatis。mybatis中的配置都会交给spring,所以很多配置都是在springContext.xml 里面去配置。
<configuration>
<!--开启下划线转驼峰标识-->
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
</configuration>
6.JDBC.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?allowMultiQueries=true
jdbc.username=root
jdbc.password=root
7.Spring 配置
<!--spring希望管理所有的业务主键-->
<context:component-scan base-package="cn.guet">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!-- 引入数据库的配置文件 -->
<context:property-placeholder location="classpath:jdbc.properties" />
<!-- Spring用来控制业务逻辑。数据源、事务控制、aop -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="jdbcUrl" value="${jdbc.url}"></property>
<property name="driverClass" value="${jdbc.driver}"></property>
<property name="user" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!-- spring事务管理 -->
<bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 开启基于注解的事务 -->
<tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>
<!--
整合mybatis 目的:1、spring管理所有组件。mapper的实现类。service==>Dao @Autowired:自动注入mapper;
2、spring用来管理事务,spring声明式事务-->
<!--创建出SqlSessionFactory对象 -->
<!--让spring的IOC一启动就代替我们去创建sqlSessionFactory对象-->
<bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<!-- configLocation指定全局配置文件的位置 -->
<property name="configLocation" value="classpath:mybatis-config.xml"></property>
<!--mapperLocations: 指定mapper文件的位置-->
<!--<property name="mapperLocations" value="classpath:mybatis/mapper/*.xml"></property>-->
</bean>
<!--配置一个可以进行批量执行的sqlSession -->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg name="sqlSessionFactory" ref="sqlSessionFactoryBean"></constructor-arg>
<constructor-arg name="executorType" value="BATCH"></constructor-arg>
</bean>
<!-- 扫描所有的mapper接口的实现,让这些mapper能够自动注入;
base-package:指定mapper接口的包名
-->
<mybatis-spring:scan base-package="cn.guet.dao"></mybatis-spring:scan>
<!-- <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.atguigu.mybatis.dao"></property>
</bean> -->
注:如果你的web. xml 是如下版本,默认是禁用 el 表达式的,需要手动开启
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<%--开启EL表达式--%>
<%@ page isELIgnored="false" %>
三、Mybatis 运行原理
四、Mybatis 插件开发
MyBatis 3的更多相关文章
- 【分享】标准springMVC+mybatis项目maven搭建最精简教程
文章由来:公司有个实习同学需要做毕业设计,不会搭建环境,我就代劳了,顺便分享给刚入门的小伙伴,我是自学的JAVA,所以我懂的.... (大图直接观看显示很模糊,请在图片上点击右键然后在新窗口打开看) ...
- Java MyBatis 插入数据库返回主键
最近在搞一个电商系统中由于业务需求,需要在插入一条产品信息后返回产品Id,刚开始遇到一些坑,这里做下笔记,以防今后忘记. 类似下面这段代码一样获取插入后的主键 User user = new User ...
- [原创]mybatis中整合ehcache缓存框架的使用
mybatis整合ehcache缓存框架的使用 mybaits的二级缓存是mapper范围级别,除了在SqlMapConfig.xml设置二级缓存的总开关,还要在具体的mapper.xml中开启二级缓 ...
- 【SSM框架】Spring + Springmvc + Mybatis 基本框架搭建集成教程
本文将讲解SSM框架的基本搭建集成,并有一个简单demo案例 说明:1.本文暂未使用maven集成,jar包需要手动导入. 2.本文为基础教程,大神切勿见笑. 3.如果对您学习有帮助,欢迎各种转载,注 ...
- mybatis plugins实现项目【全局】读写分离
在之前的文章中讲述过数据库主从同步和通过注解来为部分方法切换数据源实现读写分离 注解实现读写分离: http://www.cnblogs.com/xiaochangwei/p/4961807.html ...
- MyBatis基础入门--知识点总结
对原生态jdbc程序的问题总结 下面是一个传统的jdbc连接oracle数据库的标准代码: public static void main(String[] args) throws Exceptio ...
- Mybatis XML配置
Mybatis常用带有禁用缓存的XML配置 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE ...
- MyBatis源码分析(一)开篇
源码学习的好处不用多说,Mybatis源码量少.逻辑简单,将写个系列文章来学习. SqlSession Mybatis的使用入口位于org.apache.ibatis.session包中的SqlSes ...
- (整理)MyBatis入门教程(一)
本文转载: http://www.cnblogs.com/hellokitty1/p/5216025.html#3591383 本人文笔不行,根据上面博客内容引导,自己整理了一些东西 首先给大家推荐几 ...
- MyBatis6:MyBatis集成Spring事物管理(下篇)
前言 前一篇文章<MyBatis5:MyBatis集成Spring事物管理(上篇)>复习了MyBatis的基本使用以及使用Spring管理MyBatis的事物的做法,本文的目的是在这个的基 ...
随机推荐
- TypeScript 上手教程
无疑,对于大型项目来说,Vanilla Js 无法满足工程需求.早在 2016 年 Anuglar 在项目中引入 TypeScript 时,大概也是考虑到强类型约束对于大型工程的必要性,具体选型考虑可 ...
- java~使用自己的maven本地仓库
本地仓库 主要是一种缓存,当你使用远程仓库中下载组件后,它下一次会优先从本地进行加载,一般位于USER_HOME/.m2目录下,我们自己也可以建立公用的包,把包发布到本地仓库,自己在其它项目里直接可以 ...
- @vue-cli3安装element组件过程
在创建好的项目目录下 执行: vue add element 如图选择对应的选项 安装成功!KO!
- Tushare模块
.TuShare简介和环境安装 TuShare是一个著名的免费.开源的python财经数据接口包.其官网主页为:TuShare -财经数据接口包.该接口包如今提供了大量的金融数据,涵盖了股票.基本面. ...
- AspNetCore 多环境配置 以及注册 消费Consul
本文主要记录 CoreApi 的多环境配置以及如何消费在consul中注册的Api 服务 1.创建三个CoreApi 我们在项目中创建三个站点分别为 UserServices “用户服务”,Order ...
- Eureka的工作原理以及它与ZooKeeper的区别
1.Eureka 简介: Eureka 是 Netflix 出品的用于实现服务注册和发现的工具. Spring Cloud 集成了 Eureka,并提供了开箱即用的支持.其中, Eureka 又可细分 ...
- 【开源分享】微信营销系统(第三方微信平台)github 开源
升讯威微信营销系统(微信第三方平台) 在线体验:http://wxcm.eeipo.cn/开源地址GitHub:https://github.com/iccb1013/Sheng.WeixinCons ...
- mysql触发器new和old
下面为您介绍mysql触发器new old的相关知识,供您参考学习,如果您在mysql触发器方面遇到过类似的问题,不妨一看,相信对您会有所帮助. mysql触发器new old: "NEW ...
- 深入理解Git的实现原理
0.导读 本文适合对git有过接触,但知其然不知其所以然的小伙伴,也适合想要学习git的初学者,通过这篇文章,能让大家对git有豁然开朗的感觉.在写作过程中,我力求通俗易懂,深入浅出,不堆砌概 ...
- EOS开发入门
EOS开发入门 在上一篇文章<EOS开发环境搭建>中,我们已经完成了EOS开发环境的搭建,本次为大家带来的是EOS开发入门的相关内容. 1. EOS的合约开发基础 智能合约是一种旨 ...