Mybatis持久层框架
一、Mybatis简介
1.1 Mybatis是什么
- MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。
- MyBatis 避免了几乎所有的 JDBC代码和手动设置参数以及获取结果集。
- MyBatis 可以使用简单的 XML 或注解来配置和映射原生类型、接口和 Java 的POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
Mybatis 3的官网链接>>>
1.2 ORM是什么
- ORM(Object Relational Mapping)
- 编写程序的时候,以面向对象的方式处理数据
- 保存数据的时候,却以关系型数据库的方式存储
- ORM解决方案包含下面四个部分
- 在持久化对象上执行基本的增、删、改、查操作
- 对持久化对象提供一种查询语言或者API
- 对象关系映射工具
- 提供与事务对象交互、执行检查、延迟加载以及其他优化功能
1.3 Mybatis与Hibernate
Hibernate优势
- Hibernate的DAO层开发比MyBatis简单,Mybatis需要维护SQL和结果映射。
- Hibernate对对象的维护和缓存要比MyBatis好,对增删改查的对象的维护要方便。
- Hibernate数据库移植性很好,MyBatis的数据库移植性不好,不同的数据库需要写不同SQL。
- Hibernate有更好的二级缓存机制,可以使用第三方缓存。MyBatis本身提供的缓存机制不佳。
Mybatis优势
- MyBatis可以进行更为细致的SQL优化,可以减少查询字段。
- MyBatis容易掌握,而Hibernate门槛较高。
总结
我们将Mybatis和Hibernate之间的区别自个用六个词做总结:
- Mybatis:小巧、方便、高效、简单、直接、半自动化
- Hibernate:强大、方便、高效、复杂、间接、全自动化
二、Mybatis的使用(SSM)
2.1 Mybatis的配置
- maven配置依赖:
<!--Mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.2</version>
</dependency>
<!--Alibaba 数据库连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<!--数据库驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.connector.version}</version>
</dependency>
- ApplicationContext.xml(Spring核心配置文件)
<!-- 启用注解 -->
<context:annotation-config />
<context:component-scan base-package="com.bosssoft.core"></context:component-scan>
<!-- 加载数据源配置文件 -->
<context:property-placeholder location="classpath:datasource.properties" />
<!--数据源 Alibaba连接池-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="driverClassName" value="${jdbc.driver}" />
<property name="maxActive" value="${jdbc.maxActive}" />
<property name="minIdle" value="${jdbc.minIdle}" />
</bean>
<!-- 配置sqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 当mybatis的xml文件和mapper接口不在相同包下时,需要用mapperLocations属性指定xml文件的路径 -->
<property name="mapperLocations" value="classpath:mapper/*.xml"/>
<!-- 指定mybatis核心配置文件 -->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 配置扫描包,加载mapper代理对象 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.bosssoft.core.dao"/>
</bean>
<!-- 使用@Transactional进行声明式事务管理需要声明下面这行 -->
<tx:annotation-driven proxy-target-class="true" />
<!-- 事务管理 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
<property name="rollbackOnCommitFailure" value="true"/>
</bean>
- datasource.properties(数据库连接池属性)
jdbc.url=jdbc:mysql://localhost:3306/login_test?characterEncoding=UTF-8
jdbc.username=root
jdbc.password=123456
jdbc.driver=com.mysql.jdbc.Driver
jdbc.maxActive=10
jdbc.minIdle=5
mybatis-config.xml
- mybatis-config.xml
<configuration>
<!--别名设置-->
<typeAliases>
<package name="com.bosssoft.core.entity"/>
</typeAliases>
</configuration>
其余属性详细设置见 Mybatis官网>>>
2.2 Mybatis-generator实现逆向工程
- 新建数据库及表,并完成:
2.根据需求更改配置文件generator.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<!--数据库驱动-->
<classPathEntry location="mysql-connector-java-5.1.7-bin.jar"/>
<context id="MySQLTables" targetRuntime="MyBatis3">
<commentGenerator>
<property name="suppressDate" value="true"/>
<property name="suppressAllComments" value="true"/>
</commentGenerator>
<!--数据库链接地址账号密码-->
<jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost/mybatis_work" userId="root" password="123456">
</jdbcConnection>
<javaTypeResolver>
<property name="forceBigDecimals" value="false"/>
</javaTypeResolver>
<!--生成Model类存放位置-->
<javaModelGenerator targetPackage="com.bosssoft.core.entity" targetProject="src">
<property name="enableSubPackages" value="true"/>
<property name="trimStrings" value="true"/>
</javaModelGenerator>
<!--生成映射文件存放位置-->
<sqlMapGenerator targetPackage="Mapper" targetProject="src">
<property name="enableSubPackages" value="true"/>
</sqlMapGenerator>
<!--生成Dao类存放位置-->
<javaClientGenerator type="XMLMAPPER" targetPackage="com.bosssoft.core.dao" targetProject="src">
<property name="enableSubPackages" value="true"/>
</javaClientGenerator>
<!--生成对应表及类名-->
<table tableName="t_user" domainObjectName="User" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>
<table tableName="t_role" domainObjectName="Role" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>
<table tableName="t_resource" domainObjectName="Resource" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>
<table tableName="t_user_role" domainObjectName="UserRole" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>
<table tableName="t_role_resource" domainObjectName="RoleResource" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>
</context>
</generatorConfiguration>
- 打开命令行,运行mybatis-generator-core-1.3.6.jar,则相关文件会自动生成到src中。
java -jar mybatis-generator-core-1.3.6.jar -configfile generator.xml
2.3 Mapper映射文件
- 映射文件中参数的指定
- 如果是单个参数(基本类型、对象、Map对象)使用parameterType;
- 如果是多个参数,则无需要parameterType属性
- 方法的返回值(对象类类型)
- 如果是单个返回值(基本类型、对象、Map对象)使用resultType;
- 如果是多个参数,则需要resultMap。
<mapper namespace="com.bosssoft.core.dao.UserMapper" >
<resultMap id="BaseResultMap" type="User" >
<constructor >
<idArg column="account" jdbcType="VARCHAR" javaType="java.lang.String" />
<arg column="password" jdbcType="VARCHAR" javaType="java.lang.String" />
</constructor>
</resultMap>
<sql id="Base_Column_List" >
account,password
</sql>
<select id="getUser" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from user
where account = #{account,jdbcType=VARCHAR} and password = #{password,jdbcType=VARCHAR}
</select>
</mapper>
2.4 动态SQL
MyBatis 的强大特性之一便是它的动态 SQL。如果你有使用 JDBC 或其它类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句的痛苦。例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL 这一特性可以彻底摆脱这种痛苦。
虽然在以前使用动态 SQL 并非一件易事,但正是 MyBatis 提供了可以被用在任意 SQL 映射语句中的强大的动态 SQL 语言得以改进这种情形。
动态 SQL 元素和 JSTL 或基于类似 XML 的文本处理器相似。在 MyBatis 之前的版本中,有很多元素需要花时间了解。MyBatis 3 大大精简了元素种类,现在只需学习原来一半的元素便可。MyBatis 采用功能强大的基于 OGNL 的表达式来淘汰其它大部分元素。
- if
- choose (when, otherwise)
- trim (where, set)
- foreach
<select id="findActiveBlogLike"
resultType="Blog">
SELECT * FROM BLOG
<where>
<if test="state != null">
state = #{state}
</if>
<if test="title != null">
AND title like #{title}
</if>
<if test="author != null and author.name != null">
AND author_name like #{author.name}
</if>
</where>
</select>
where 元素只会在至少有一个子元素的条件返回 SQL 子句的情况下才去插入“WHERE”子句。而且,若语句的开头为“AND”或“OR”,where 元素也会将它们去除。
2.5 MyBatis关联配置
- 关联结果的配置与使用
在一方配置collection节点,在多方配置association 节点。(一对多)
一方:
<resultMap type="blog" id="blogResult">
<id column="id" property="id"/>
<result column="title" property="title"/>
<result column="content" property="content"/>
<result column="create_time" property="createTime"/>
<result column="type" property="type"/>
<collection property="comments" column="id" javaType="ArrayList" ofType="comment" select="selectComments"/> //ofType为集合中保存的类型
</resultMap>
<select id="selectComments" parameterType="int" resultType="comment">
select * from comment where blog_id = #{id}
</select>
<select id="selectBlogs" resultMap="blogResult" >select * from blog</select>//常规查询
多方:
<resultMap type="comment" id="commentResult">
<id property="id" column="author_id"/>
<result property="createDate" column="date"/>
<result property="......." column="..."/>
<association property="blog"
column="blog_id"
javaType="blog" select="findBloyById"></association>
</resultMap>
<select id="findUserTypeById" parameterType="int" resultType="blog">
select * from blog where id=#{id}
</select>
- 集合映射的配置与使用
在select中指定一个查询语句来获取查询结果,此查询语句使用连接查询来配置:
<select id="selectBlogById" resultMap="blogResult" parameterType="int">
select
B.id,B.title,B.author_id,B.content,
B.create_time,B.type,A.id,A.username,
A.password,A.email,A.address,A.phone
from Blog B left outer join Author A on B.author_id = A.id
</select>
在blogResult中如下声明:
<resultMap type="blog" id="blogResult">
<id column="id" property="id"/>
<result column="title" property="title"/>
..............
<collection property="comment" column="blog_id"
javaType="java.util.Set" ofType="comment"
resultMap="commentResult"></collection>
commentResult是关联表的字段声明,需要注意的是只包含基本类型的字段,也就是说 这种嵌套map只能用于单向关联