Mybatis3.2.3 知识点快速摘要
摘要: 基于mybatis官网上的doc整理了一个快速摘要
Mybatis的好处
- 节省了JDBC方式下手写代码的工作量, 主要的节省在于自动按照resultMap返回结果类型的对象或对象集合甚至Map;
- 对sql语句直接编写方便DBA或程序员自己对sql语句优化
- 相对hibernate映射ORM的方式, 学习成本低
Mybatis环境搭建
- 核心包: 十分简洁方便, 只用一个mybatis-x.x.x.jar
- 依赖包: 主要就是logging用的包, 提供了对各种方式logging的支持
- 配置文件: 需要两种配置文件
§ 全局配置文件: 数据开发环境配置, mybatis性能配置, mapper资源索引
§ Mapper配置文件: 一种sql存储流程的配置, 包括配置输入参数, sql语句模块, 结果的类型配置
Mybatis 全局配置
上图是Mybatis全局配置的一个简易视图:彩色模块是常用主要配置,无背景色部分配置较少(一些高级的配置),这里忽略介绍.
<properties>
用于加载一些配置用的properties文件以及在整个配置文件开头定义一些需要用到的属性常量用于全局的引用
<propertiesresource="mysql.properties"> <propertyname="username"value="root"/> <property name="password"value="root"/> </properties> |
<typeAliases>
此处指定一些全局可用的类型的别名主要为了简化书写, 这些typeAliases可以在mapper文件中被type/resultType属性引用.
<typeAliases> <typeAliastype="cn.itcast.mybatis.User"alias="user"/> <typeAliastype="cn.itcast.mybatis.Order"alias="order"/> </typeAliases> |
<environments>
配置JDBC数据库连接的环境配置信息:
几点注意的是:
- 可以配置多个<environment>, 在<environments>- default属性上指定应用哪个
- 配置数据库连接需要: dataSource和transactionManager
- dataSource有3种type配置: POOLED|UNPOOLED|JNDI: 选择POOLED
- transactionManager有2种type配置: JDBC|MANAGED 和第三方整合时,选择MANAGED
<environments> <environmentid="development"> <transactionManagertype="JDBC"> <propertyname="..."value="..."/> </transactionManager> <dataSourcetype="POOLED"> <propertyname="driver"value="${driver}"/> <propertyname="url"value="${url}"/> <propertyname="username"value="${username}"/> <propertyname="password"value="${password}"/> </dataSource> </environment> </environments> |
<mapper>
配置所有mapper配置文件的路径
<mappers> <mapperresource="user.xml" /> <mapperresource="order.xml" /> </mappers> |
Mapper配置文件
Mapper的配置就像一个函数的执行过程, 定义参数, 选择执行语句, 定义输出的接受类型,函数中可以调用动态sql以增强sql语言的表达能力.
parameterType
这个是<select/insert/update/delete>的一个属性: 可选的输入有3种类型的参数容器实体,基本类型,指定的用户自定义类型,map的键值对组合
需要说明的是:在这个文件中,parameterTpye只是负责定义Type的, 实际的参数容器实体的传入是通过mybatis的javaAPI调用的时候传入的
Sql语句中获取参数的方式有: #{paramName} 和 ${paramName}两种:
- #{}方式的取值采用PreparedStatement的方式替换”?“部分的sql
- ${}方式的采用字符串拼接(“…”+param+”…”)的方式拼接成完整的sql
- map或者用户自定义类型的parameterType必须保证#/${}内的paramName是map的一个键或者对应用户自定义类型(JavaBean)的一个getter的属性名称
<select id="findByUserId" parameterType="int" resultMap="userRM" > select * from user u,orders o where u.user_id=#{id} </select> |
<select id="findUserByCondition" parameterType="map" resultMap="userRM"> select * from user u,orders o where u.user_name=#{name} and u.user_age= #{age} </select> |
<update id="updateUser" parameterType="cn.itcast.mybatis.User"> update user t set t.user_name=#{name} where t.user_id=#{id} </update> |
<select/insert/update/delete>
此部分满足sql语法规范, 需要注意的一点就是何时使用#{}传参, 何时使用${}传参: - LIKE %${paramName}%: 此处用拼接 - ORDERBY ${paramName}: 此处用拼接 |
动态Sql语句的增强
- <sql>: 提供一个sql语句片段的重用
<sql id="userFullColumns"> user_id,user_name,user_age </sql> |
- <where><if>:用于选择性查询时空值查询的问题,当有where是, 自动处理and拼接问题, 当if不存在一样写sql语句即可
select <includerefid="userFullColumns"/> from user u <where> <if test="name != null"> u.user_name like '%${name}%' </if> <if test="age != null"> and u.user_age=#{age} </if> </where> |
- <set><if>: 用于update是属性为null的空值替换问题,会自动处理,的拼接问题,当if不存在一样书写sql语句即可
update user t <set> <if test="name!=null">t.user_name=#{name},</if> <if test="age!=null">t.user_age=#{age}</if> </set> where t.user_id=#{id} |
- <foreach> : 用于in(xxx,xxx,xxx)或者批量插入的情景,可以设置open,close, seperator, item, ofType等
select <includerefid="userFullColumns"/> from user where user_id in <foreachcollection="list"open="("close=")" item="id" separator=","> #{id} </foreach> |
<resultMap>
resultMap指定了一个结果输出的样式. 结果的输出有两种样式,另一种是resultType,可以指定一个类型,一般是一个自定义的JavaBean.其实当指定结果样式是resultType时, 默认生成一个resultMap,这个resultMap的自动将column每个字段(字段的别名)的值去JavaBean中寻找响应的setter,如果恰好JavaBean的setter的属性名称和表的column的字段(别名)名称一致就可以匹配输出.
而自定义resultMap就是设定JavaBean和表的映射关系. 我们需要考虑:
- 构造函数初始化注入: <constructor>:避免暴露一些属性的setter来初始化
- 主键: <id>
- 普通的属性: <result>
- 如果存在外键关系映射:
o <collection> :property+column+ofType+[javaType]+[resultMap]+[select]
§ javaTpye不定义, mybatis也可以自己解析
§ 如果抽取了ofType的resultMap,可以用resultMap
§ 如果结果是由另一个查询得到的, 即用select指定一个子查询
o <association>:property+column+[javaType]+[resultType]+[select] 同理
注意:当resultMap分布在不同的mapper配置文件中时, 是无法相互引用的.
<collectionproperty="posts"ofType="domain.blog.Post"> <id property="id" column="post_id"/> <result property="subject" column="post_subject"/> <result property="body" column="post_body"/> </collection> <! -- 抽取resultMap --> <collectionproperty="posts"resultMap="post"/> <resultMapid="post"type="domain.blog.Post"> <idproperty="id"column="post_id"/> <resultproperty="subject"column="post_subject"/> <resultproperty="body"column="post_body"/> </resultMap> |
<resultMap id="blogResult" type="Blog"> <collectionproperty="posts"javaType="ArrayList"column="id"ofType="Post" select="selectPostsForBlog"/> </resultMap>
<select id="selectBlog" parameterType="int" resultMap="blogResult"> SELECT * FROM BLOG WHERE ID = #{id} </select>
<select id="selectPostsForBlog" parameterType="int"resultType="Blog"> SELECT * FROM POST WHERE BLOG_ID = #{id} </select> |
- 条件结果容器选择:<discriminate>
o Discriminate用来甄别选择哪种类型resultMap作为结果的接受容器
o 一种实际的应用场景是: 数据库中的一个类型选择字段, 而且有一些公用的字段数据,那么,抽取一个commonMap,在commonMap中针对这个类型选择字段result_type的<discriminator>,类型类别的<resultMapextends=”commonMap”/>, 这样,选中的类型就可以拥有公共的字段和自己独有字段,而没有匹配的只包含commonMap中的属性.
<resultMap id="vehicleResult" type="Vehicle"> <id property="id" column="id" /> <result property="vin" column="vin"/> <result property="year" column="year"/> <result property="make" column="make"/> <result property="model" column="model"/> <result property="color" column="color"/> <discriminatorjavaType="int"column="vehicle_type"> <case value="1"resultMap="carResult"/> <case value="2" resultMap="truckResult"/> <case value="3" resultMap="vanResult"/> <case value="4" resultMap="suvResult"/> </discriminator> </resultMap>
<resultMap id="carResult" type="Car" extends="vehicleResult"> <result property="doorCount" column="door_count" /> </resultMap>
|
- columnPrefix属性: 当返回的结果为了区分开各个表中的字段而起了不同的前缀别名时,用columnPrefix=”xxx”来过滤特定的属性字段
<resultMap id="blogResult" type="Blog"> <idproperty="id"column="blog_id"/> <resultproperty="title"column="blog_title"/> <associationproperty="author"resultMap="authorResult"/> <associationproperty="coAuthor"resultMap="authorResult" columnPrefix="co_"/> </resultMap> |
MyBatis核心初始化流程
public class QuickStartTest { // 只是一个实例,没有进行异常的处理, 关流应try-catch-finally SqlSession session; String ns="cn.itcast.mybatis.User."; @Before public void setup() throws IOException{ String resource="config.xml"; InputStream in=Resources.getResourceAsStream(resource); SqlSessionFactory sessionFactory = newSqlSessionFactoryBuilder().build(in); session = sessionFactory.openSession(); } @Test public void test() throws IOException{ //配置过resultType后就无需强转 User user = session.selectOne("cn.itcast.mybatis.User.findByUserId",1); System.out.println(user); } @After public void cleanup(){ session.close(); } } |