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的事物的做法,本文的目的是在这个的基 ...
随机推荐
- 配置Nginx部署静态资源和自动跳转到https
一.首先在阿里云后台添加域名解析: 二.两个网站的静态资源在以下目录: /www/temp/blog/public 三.在服务器端配置nginx: cd /etc/nginx/conf.d 添加两个文 ...
- 表单数据验证方法(二)——ASP.NET后台验证
昨天写了一下关于如何在前台快捷实现表单数据验证的方法,今天接着昨天的,把后台实现数据验证的方法记录一下.先说明一下哈,我用的是asp.net,所以后台验证方法也是基于.net mvc来做的. 好了,闲 ...
- Raptor井字棋游戏
作为大学第一个小作品,记录一下,也给那些想接触到Raptor游戏的人一个小小的参考QAQ至于Raptor的语法和使用,可以参考一下他的帮助手册,看不懂英文的话可以复制放到翻译上看. 以上是主函数 以下 ...
- Vb.net MakeLong MAKELPARAM 合并整数代码
Function MAKELPARAM(wLow As UShort, wHigh As UShort) As UInteger Return wHigh * &H10000 + wLow E ...
- Manacher's Algorithm(马拉车算法)
## 背景 该算法用于求字符串的最长回文子串长度. ## 参考文章 >[最长回文子串——Manacher 算法](https://segmentfault.com/a/1190000003914 ...
- 观察者模式 Observer 发布订阅模式 源 监听 行为型 设计模式(二十三)
观察者模式 Observer 意图 定义对象一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖他的对象都得到通知并自动更新. 别名:依赖(Dependents),发布订阅(Publish-Su ...
- iBatis第二章:搭建一个简单的iBatis开发环境
使用 iBatis 框架开发的基本步骤如下:1.新建项目(iBatis是持久层框架,可以运用到java工程或者web工程都可以) 这里我们建立一个 web 工程测试. 2.导入相应的框架 jar 包 ...
- PYTHON定义函数制作简单登录程序(详细)
环境:python3.* 结构: dict_name = {} #定义一个字典,后面用到 def newuser(): #定义注册函数 prompt1='login desired:' while ...
- SQL语句将一个表的数据写入到另一个表中
在日常的数据库运维过程中,有时候需要将Select查询出来的数据集写入到另一个数据表中,其中一种方式是通过存储过程循环写入数据,另一种简便的方式是直接使用Insert Into语句后面跟上Select ...
- Windows下Oracle 11g的安装
Windows下Oracle 11g的安装 Windows下Oracle 11g的安装: Windows:64位, Oracle 11g版本:win64_11gR2_database_1of2(安装包 ...