Mybatis3学习日记。
来源:互联网 发布:网络被高智慧生物屏蔽 编辑:程序博客网 时间:2024/06/11 05:26
Mybatis学习
Mybatis和hibernate同属于ORM框架,其中两者最显著的区别就在于hibernate是全自动框架,不是开发人员手写sql语句,但配置相对繁琐。Mybatis则是半自动化ORM框架,与数据库交互的语句都需要自己来写。
Mybatis使用的核心是SqlsessionFactory对象的实例,而SqlsessionFactory对象的实例可以通过SqlsessionFactoryBuilder对象来获得,SqlsessionFactoryBuilder可以通过配置XML来获取,有点晕了,直接看代码吧。
从XML中构建SqlsessionFactory
下面这个xml的配置信息是Mybatis的基础配置信息,包括对数据库的连接信息和实体类对应的mapper.xml的映射。
<span style="font-size:14px;"><?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><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/mysql"/><property name="username" value="root"/><property name="password" value="root"/></dataSource></environment></environments><mappers><mapper resource="org/mybatis/example/BlogMapper.xml"/></mappers></configuration></span>接下来就使用Java代码来获取SqlSessionFactory对象实例并执行接口中定义的查询方法
<span style="font-size:14px;">package org.mybatis.test;import java.io.IOException;import java.io.Reader;import java.util.List;import org.apache.ibatis.io.Resources;import org.apache.ibatis.session.SqlSession;import org.apache.ibatis.session.SqlSessionFactory;import org.apache.ibatis.session.SqlSessionFactoryBuilder;import org.mybatis.example.Blog;import org.mybatis.example.BlogMapper;public class MybatisTest {public static void main(String[] args) throws IOException {SqlSessionFactory sqlMapper = null;String resource = "classpath:Configuration.xml";Reader reader = Resources.getResourceAsReader(resource);sqlMapper = new SqlSessionFactoryBuilder().build(reader);SqlSession session = sqlMapper.openSession();BlogMapper blogMapper = session.getMapper(BlogMapper.class);List<Blog> list = blogMapper.selectAll();}}</span>如上所示,最终取得的SqlSession中包含了数据库的连接信息和实体类对应的xml文件映射,这样就可以直接使用接口来进行方法的调用了。
接下来说一下Mybatis的xml配置文件属性信息,先看一下配置文件的高层结构有哪些。
configuration配置
typeAlias:是为Java类型命名一个短的名字,而不至于每次使用java类型都需要带上包名,下面看个示例
transactionManager是Mybatis对事务的管理,管理器类型有2种,
随机ID生成方法
association:用来处理“有一个”类型的关系,“有一个”表示当前查询表与外键表的关系为“一对一”或者“多对一”的关系,关联映射就映射在这种结果上。
- properties属性
- settings设置
- typeAliases类型命名
- typeHandlers类型处理器
- objectFactory对象工厂
- plugins插件
- environments环境
- environment环境变量
- transactionManager事务管理器
- dataSource数据源
- 映射器
properties属性可以对配置进行赋值,格式为<property name = "" value=""/>
settings是对Mybatis运行的机制进行设置的,全部的属性设置有这些:
<span style="font-size:14px;"><settings><setting name="cacheEnabled" value="true"/>--是全局映射器启用或禁用缓存<setting name="lazyLoadingEnabled" value="true"/>--全局启用或禁用延迟加载<setting name="multipleResultSetsEnabled" value="true"/>--允许或不允许多种结果集从一个单独的语句中返回<setting name="useColumnLabel" value="true"/>--使用列标签代替列名<setting name="useGeneratedKeys" value="false"/>--允许JDBC支持生成的键<setting name="enhancementEnabled" value="false"/>--全局性地启用或禁用运行时字节码增强<setting name="defaultExecutorType" value="SIMPLE"/>--配置默认的执行器。SIMPLE执行器没有什么特别之处。REUSE执行器重用预处理语句。BATCH执行器重用语句和批量更新<setting name="defaultStatementTimeout" value="25000"/>--设置超时时间</settings></span>
<typeAliases><typeAlias alias="Blog" type="domain.blog.Blog"/></typeAliases>这样配置的好处是,在使用到Blog类的地方,只需要书写上Blog就可以,而不用书写完整的类名。
environments是用来配置多种环境的,在配置多种环境的时候,SqlSessionFactory只能选择一个。
transactionManager是Mybatis对事务的管理,管理器类型有2种,
1.JDBC - 这个配置直接简单使用了JDBC的提交和回滚设置。它依赖于从数据源得到的连接来管理事务范围。
2.MANGED - 这个配置几乎没做什么。它从来不提交或回滚一个连接。而它会让容器来管理事务的整个生命周期。
dataSource是对数据库资源配置的属性,数据源类型分为3种
1.UNPOOLED这个数据源的实现是每次被请求时简单打开和关闭连接,只能配置一下5种属性值,driver、url、username、password、defaultTransactionIsolationLevel(默认的连接事务隔离级别)
2.POOLED这是JDBC连接对象的数据源连接池的实现,用来避免创建新的连接实例时必要的初始连接和认证时间,除了上述的那5种属性外还可以配置以下属性,
- poolMaximumActiveConnections – 在任意时间存在的活动(也就是正在使用)连接的数量。默认值:10
- poolMaximumIdleConnections – 任意时间存在的空闲连接数。
- poolMaximumCheckoutTime – 在被强制返回之前,池中连接被检查的时间。默认值:20000毫秒(也就是20秒)
- poolTimeToWait – 这是给连接池一个打印日志状态机会的低层次设置,还有重新尝试获得连接,这些情况下往往需要很长时间(为了避免连接池没有配置时静默失败)。默认值:20000毫秒(也就是20秒)
- poolPingQuery – 发送到数据的侦测查询,用来验证连接是否正常工作,并且准备接受请求。默认是“NO PING QUERY SET”,这会引起许多数据库驱动连接由一个错误信息而导致失败。
- poolPingEnabled – 这是开启或禁用侦测查询。如果开启,你必须用一个合法的SQL语句(最好是很快速的)设置poolPingQuery属性。默认值:false。
- poolPingConnectionsNotUsedFor – 这是用来配置poolPingQuery多次时间被用一次。这可以被设置匹配标准的数据库连接超时时间,来避免不必要的侦测。默认值:0(也就是所有连接每一时刻都被侦测-但仅仅当poolPingEnabled为true时适用)。
mappers是对sql语句映射的设置,大多使用相对于类路径的资源来确认sql映射文件的位置。以下是映射文件的顶级元素
1. cache - 配置给定命名空间的缓存
2. cache - ref 从其他命名空间引用缓存配置
3. resultMap 描述从数据库取出数据来加载对象
4. sql 可以重用的sql块,可以被其他语句引用
以及insert select delete update这4种对数据库的常用操作命令。
select元素是最常用的数据库查询语句,元素有很多属性可以配置,以下详细描述
<span style="font-size:14px;"><select id=”selectPerson” parameterType=”int” parameterMap=”deprecated” resultType=”hashmap”resultMap=”personResultMap”flushCache=”false”useCache=”true”timeout=”10000”fetchSize=”256”statementType=”PREPARED”resultSetType=”FORWARD_ONLY”></span>
- id:命名空间唯一的标识符
- parameterType:sql语句用到的参数类型
- resultType:sql语句返回的结果类型,不能与resultMap同时使用
- resultMap:可以对多个表信息的返回进行定制
- flushCache:无论什么语句被执行,都会对缓存进行清空
- useCache:将本条语句的结果缓存
- timeOut:连接数据库的超时时间限制
- fetchSize:每次批量返回的行数,默认不设置
- statementType:STATEMENT,PREPARED,CALLABLE,相当于从statement、preparedStatement、CallableStatement中选择一个
- resultSetTYpe:默认不设置
insert语句相较于select的属性,多了一个useGeneratedKeys,设置true表示主键自增。当不支持主键自增时,可以使用下面这种方式来手动给主键赋值
<insert id="insertAuthor" parameterType="domain.blog.Author" flushCache="true" statementType="PREPARED" keyProperty=""useGeneratedKeys="true" timeout="20000">
还有1个KeyPorperty,这个属性用来标记一个属性,只对insert有效,默认不设置,在下面的随机定义主键id时会使用。
随机ID生成方法
<insert id="insertAuthor" parameterType="domain.blog.Author"><selectKey keyProperty="id" resultType="int" order="BEFORE">select CAST(RANDOM()*1000000 as INTEGER) a from SYSIBM.SYSDUMMY1</selectKey>insert into Author(id, username, password, email,bio, favourite_section)values(#{id}, #{username}, #{password}, #{email}, #{bio},#{favouriteSection,jdbcType=VARCHAR})</insert>
KeyProperty:selectKey语句结果应该被设置为目标属性
resultType:结果类型
order:可以被设置为BEFORE或者AFTER,区别在于是否先对主键进行赋值
statementType:同上
Sql这个元素可以被用来定义重用的代码段,可以被包含在其他的语句中,如下所示
<sql id=”userColumns”> id,username,password </sql><select id=”selectUsers” parameterType=”int” resultType=”hashmap”>select <include refid=”userColumns”/>from some_table where id = #{id}</select>可以对所有sql语句中的公共部分进行设置,以减少代码的书写和保证字段的正确性。
resultMap是mybatis中最重要的元素,相较于resultType的单一指定数据类型或者javaBean类,resultMap可以自由组合多表数据列。下面看一下最简单的应用,先定义一个resultMap,字段信息有3个
<resultMap id="userResultMap" type="User"><id property="id" column="user_id" /><result property="username" column="user_name"/><result property="password" column="hashed_password"/></resultMap>然后在查询语句中进行引用
<select id=”selectUsers” parameterType=”int”resultMap=”userResultMap”>select user_id, user_name, hashed_password from some_table where id = #{id}</select>这是对resultMap最简单的应用,返回字段为User类的字段信息,在select属性中进行引用。如果要求返回类型为多表字段的组合该怎么办?
<select id="selectBlogDetails" parameterType="int"resultMap="detailedBlogResultMap">select B.id as blog_id,B.title as blog_title,B.author_id as blog_author_id,A.id as author_id,A.username as author_username,A.password as author_password,A.email as author_email,A.bio as author_bio,A.favourite_section as author_favourite_section,P.id as post_id,P.blog_id as post_blog_id,P.author_id as post_author_id,P.created_on as post_created_on,P.section as post_section,P.subject as post_subject,P.draft as draft,P.body as post_body,C.id as comment_id,C.post_id as comment_post_id,C.name as comment_name,C.comment as comment_text,T.id as tag_id,T.name as tag_name from Blog Bleft outer join Author A on B.author_id = A.id left outer join Post P on B.id = P.blog_idleft outer join Comment C on P.id = C.post_id left outer join Post_Tag PT on PT.post_id = P.idleft outer join Tag T on PT.tag_id = T.id where B.id = #{id}</select>这是一个多表查询的select语句,对于这样的多表查询,返回结果类型该怎么定义?
<resultMap id="detailedBlogResultMap" type="Blog"><constructor><idArg column="blog_id" javaType="int"/></constructor><result property="title" column="blog_title"/><association property="author" column="blog_author_id" javaType=" Author"><id property="id" column="author_id"/><result property="username" column="author_username"/><result property="password" column="author_password"/><result property="email" column="author_email"/><result property="bio" column="author_bio"/><result property="favouriteSection" column="author_favourite_section"/></association><collection property="posts" ofType="Post"><id property="id" column="post_id"/><result property="subject" column="post_subject"/><association property="author" column="post_author_id" javaType="Author"/><collection property="comments" column="post_id" ofType=" Comment"><id property="id" column="comment_id"/></collection><collection property="tags" column="post_id" ofType=" Tag" ><id property="id" column="tag_id"/></collection><discriminator javaType="int" column="draft"><case value="1" resultType="DraftPost"/></discriminator></collection></resultMap>这个resultMap是对上面的多表联接查询的结果集设置,其中的属性非常多,一个一个来说。
constructor:用来向实体类中的构造方法进行值的设置,属性有2个,分别为
idArg:ID参数
arg:注入到构造方法的一个普通结果
<constructor><idArg column="id" javaType="int"/><arg column=”username” javaType=”String”/></constructor>
association:用来处理“有一个”类型的关系,“有一个”表示当前查询表与外键表的关系为“一对一”或者“多对一”的关系,关联映射就映射在这种结果上。
<association property="author" column="blog_author_id" javaType=" Author"><id property="id" column="author_id"/><result property="username" column="author_username"/></association>常用的属性有:
property:映射到列的结果或者属性
column:数据库的列名,如果存在复合主键,可以使用column="{prop1=col1,prop2=col2}"这种语法来传递语句
javaType:java类名或者其他集合类型
JDBCType:支持的JDBC类型列表中的类型
typeHandler:默认的类型处理器
select:关联嵌套查询所使用的属性,如果有联合主键,使用方法同column
mybatis有2种关联方式,分别为
嵌套查询:通过执行另外一个SQL映射语句来返回预期的复杂类型
嵌套结果:通过嵌套结果映射来处理重复的联合结果的子集
嵌套查询:
<mapper namespace="org.mybatis.example.BlogMapper"><resultMap type="Blog" id="blogResultMap"><id property="id" column="id"/><result property="name" column="name"/><association property="author" column="author_id"javaType="Author" select="selectAuthor"/></resultMap><sql id="qjbl">name,pwd</sql><select id="selectAll" parameterType="int" resultMap="blogResultMap">select * from blog where id = #{id}</select><select id="selectAuthor" parameterType="int" resultType="Author">select * from author where id = #{id}</select></mapper>这就是嵌套查询的关联方式,在关联设置里使用其他定义好的<select>来进行关联数据,但是这种方式有一个弊端,如果关联的数据返回的数据不是一条,而是成百上千条的话,select所需要执行的次数就会有成百上千次,也就是所谓的N+1,这是非常不明智的举动,所以就有了嵌套结果关联的方式来解决这种返回条数过多的结果集。
嵌套结果:
<resultMap type="Blog" id="blogResultMap"><id property="id" column="id"/><result property="name" column="name"/><association property="author" column="author_id"javaType="Author" resultMap="authorResultMap"/></resultMap><resultMap type="Author" id="authorResultMap"><id property="id" column="id"/><result property="nickname" column="nickname"/></resultMap><sql id="qjbl">name,pwd</sql><select id="selectAll" parameterType="int" resultMap="blogResultMap">select a.id,a.nickname,b.id,b.name,b.pwd,b.author_id from blog b,author a where a.id = b.author_id and b.id = #{id}</select>这种嵌套结果的好处是所引用的resultMap可以重复使用,嵌套结果相较于嵌套查询,在描述上更为清晰,且不会存在N+1的问题。如果不需要这种引用方式的resultMap,也可以写成下面这种嵌套形式的。
<resultMap type="Blog" id="blogResultMap"><id property="id" column="id"/><result property="name" column="name"/><association property="author" column="author_id" javaType="Author"><id property="id" column="id"/><result property="nickname" column="nickname"/></association></resultMap>“有一个”的2种关联查询方式都说完了,那么“有多个”该怎么查询呢?
collection:集合的作用和用法与上面说的关联几乎是相同的,那么不同点在上面地方呢。那就是关联是针对“有一个”,而结果映射为多个的时候,就要用到collection了。
嵌套查询:
<resultMap type="Blog" id="blogResultMap"><id property="id" column="id"/><result property="name" column="name"/><collection property="posts" javaType="ArrayList" column="id" ofType="Post" select="selectPosts"/></resultMap><select id="selectAll" parameterType="int" resultMap="blogResultMap">select b.id,b.name,b.pwd,b.author_id from blog b where b.id = #{id}</select><select id="selectPosts" parameterType="int" resultType="Post">select * from post where blog_id = #{id}</select>
用法与关联几乎一模一样,但是有2个地方需要我们来关注,一个就是javaType属性变成了ArrayList,因为结果映射是多条数据,所以使用集合来存储。第二个地方就是多了一个OfType属性,这个属性是用来区分javabean的属性类型。ps:在很多时候javaType属性是不需要的,mybatis可以自己算出来,所以可以省略不写。
0 0
- Mybatis3学习日记。
- Mybatis3学习
- MyBATIS3入门学习笔记
- mybatis3学习笔记
- mybatis3学习笔记(一)
- Mybatis3
- 学习日记
- 学习日记
- 学习日记
- 学习日记
- 学习日记
- 学习日记
- 学习日记
- 【学习日记】
- 学习日记
- 学习日记
- 学习日记
- 学习日记
- 访问某个站点时弹出要求输入用户名和密码的窗口
- this指针
- uboot的relocation原理详细分析
- Linux网络编程基础
- 物联12:rfid天线场区、耦合形式与频率
- Mybatis3学习日记。
- AJAX学习总结(入门)
- LG华为抢先苹果发布智能手表
- 变量可以存在两种类型的值。
- android使用httppost向c# wcf发送数据总结
- java用HashSet集合判断重复问题。
- oracle查看数据库锁表情况
- 如何学好一门编程语言或技术?
- Visio安装失败 无法打开注册表项 解决方案