文章目录
- 前言
- 1.什么是框架?
- 2.什么是ORM框架?
- 3.使用JDBC完成ORM操作的缺点?
- Mybatis框架
- 简介
- 访问与下载
- MyBatis环境搭建
- pom.xml中引入MyBatis核心依赖
- 创建MyBatis配置文件
- MyBatis开发步骤
- 建表
- 定义实体类
- 编写Mapper.xml
- 注册Mapper
- 测试
- MyBatis的CRUD操作
- 查询
- 序号参数绑定
- 注解参数绑定【推荐】
- Map参数绑定
- 对象参数绑定
- 模糊查询
- 删除
- 修改
- 添加
- 主键回填
- 通过last_insert_id()查询主键
- 通过uuid查询主键
- 查询
- MyBatis工具类
- 封装工具类
- 测试工具类
- ORM映射
- MysqlBatis自动ORM失效
- 方案一:列的别名
- 方案二:结果映射
- MyBatis处理关联关系-多表连接
- OneToOne
- OneToMany
- ManyToMany
- 关系总结
- 动态SQL
- <sql>
- <if>
- <where>
- <set>
- <trim>
- <foreach>
- 缓存(Cache)
- 一级缓存
- 二级缓存
- 开启全局缓存
- 指定Mapper缓存
- 缓存清空并重新缓存
- Druid连接词
- 简介
- 不同连接池对比
- 测试环境
- 基准测试结果对比
- 测试结论
- 配置pom.xml
- 创建DruidDataSourceFactory
- 修改mybatis-config.xml
- PageHelper
- 简介
- 访问与下载
- 开发步骤
- 引入依赖
- 配置MyBatis-config.xml
- PageHelper应用方式
- PageInfo对象
- PageInfo应用方式
- 注意事项
- 分页练习
前言
1.什么是框架?
软件的半成品,解决了软件开发过程当中的普适性问题,从而简化了开发步骤,提供了开发的效率。
2.什么是ORM框架?
ORM (Object RelationalMapping) 对象关系映射,将程序中的一个对象与表中的一行数据一一对应。
ORM框架提供了持久化类与表的映射关系,在运行时参照映射文件的信息,把对象持久化到数据库中。
3.使用JDBC完成ORM操作的缺点?
- 存在大量的冗余代码。
- 手工创建 Connection、Statement等
- 手工将结果集封装成实体对象。
- 查询效率低,没有对数据访问进行过优化 (Not Cache)。
Mybatis框架
简介
MyBatis本是Apache软件基金会的一个开源项目iBatis,2010年这个项目由apache software foundation 迁移到了Google Code,并且改名为MyBatis 。2013年11月迁移到Github。
MyBatis是一个优秀的基于Java的持久层框架,支持自定义SQL,存储过程和高级映射。
MyBatis对原有JDBC操作进行了封装,几乎消除了所有JDBC代码,使开发者只需关注 SOL本身。
MyBatis可以使用简单的XML或Annotation来配置执行SQL,并自动完成ORM操作,将执行结果返回。
访问与下载
MyBatis环境搭建【重点】
pom.xml中引入MyBatis核心依赖
在pom.xml中引入相关依赖
<?xml version=~1.8” encoding=~UTF-8~?> <project xmlns=~http ://maven.apache.org/POM/4.8.8“xmIns :xsi="http://www.w3 .org/2881/XMLSchema-instancexsi:schemaLocation=http://maven .apache .org/POM/4.8.8http://maven .apache .org/xsd/maven-4 .8.8.xsd"> <cmodelVersion>4.8.8</modelVersion> <!--项目配置--> cgroupId>com.qf/groupId> <artifactId*hello-mybatis</artifactId> <version>18-SNAPSHOT</version> <!--依赖--> <dependencies> <!--MyBatis核心依赖--> <dependency> <groupIdzorg>mybatis</groupId> <artifactId>mybatis</artifactIdx <version>3.4.6</version> </dependency> <!--MySql驱动依赖--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency> </dependencies> </project>
创建MyBatis配置文件
创建并配置mybatis-config.xml
<?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> <!--JDBC环境配置,选中默认环境--> <environments default="development"> <environment id="development"> <!--事务管理--> <transactionManager type="JDBC"/> <!--连接池--> <dataSource type="POOLED"> <property name="driver" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://192.168.153.13:3306/java2305?serverTimezone=UTC"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments> <!--Mapper注册--> <mappers> <!--注册Mapper文件的所在位置--> <mapper resource="com\tt\mapper\UserMapper.xml"/> </mappers> </configuration>
MyBatis开发步骤【重点】
1.建表
create table t_users( id int primary key auto_increment, name varchar (58) , password varchar(58), sex varchar(1), birthday datetime , registTime datetime )default charset = utf8;
2 .定义实体类
定义所需CURD操作的实体类
public class User ( private Integer id; private String name ; private String password; private String sex; private Date birthday: private Date registTime; //无参构造 (必备构造二选一) public User() () //全参构造 (必备构造二选一) public User(Integer id, String name, String password, String sex, Date birthday, Date registTime) ( this.id = id; this .name = name; this .password = password; this.sex = sexi this.birthday = birthday: this.registTime = registTime:
3.定义DAO接口
根据所需Dao定义接口,以及方法
public interface UserDao(){ public User selectUserById(Integer id); }
4.编写Mapper.xml
在resource目录下创建Mapper.xml文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!---namespace = 所需实现的接口全限定名--> <mapper namespace="UserMapper"> <!--id = 所需重写的接口抽象方法,resultType = 查询后所需返回的对象类型--> <select resultType="com.tt.pojo.User" id="getAll">select * from User</select> </mapper>
5.注册Mapper
将Mapper.xml注册到mybatis-config.xml中
<!--Mapper文件注册位置--> <mappers> <!--注册Mapper文件--> <mapper resource="UserDaoMapper.xml"/> </mappers>
6.测试一
public class HelloMyBatis ( @Test public woid test1() throws IOException ( //1.获得读取MyBatis配置文件的流对象 InputStream is = Resources.getResourceAsStream("mybatis-config.xml"); //2.构建Sq1Session连接对象的工厂 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is); //3.通过工厂获得连接对象 SqlSession sqlSession = factory .openSession() : /4.通过连接对象获得接口实现类对象 List<Object> objects = sqlSession.selectList("UserMapper.getAll"); for (Object object : objects) { System.out.println(object); } }
MyBatis的CRUD操作【重点】
查询
标签:<select id=" " resultType=" " >
1.序号参数绑定
public interface UserDao { //使用原生参数绑定 public User selectUserByIdAndPwd(Integer id , String pwd); } <select id="selectUserByIdAndPwd” resultType="user"> SELECT * FROM t_users WHERE id = #{id} AND password = #{password} </select> <select id="selectUserByIdAndPwd” resultType="user"> SELECT * FROM t_usersWHERE id = #{id1} AND password = #{param2} </select>
2.注解参数绑定【推荐】
import org.apache.ibatis.annotations.Param; public interface UserDao { //使用MyBatis提供的@Param进行参数绑定 public User selectUserByIdAndPwd(@Param("id")Integer id, @Param("pass") String pwd); } <select id="selectUserByIdAndPwd" resultType="user"> select*from t_users where id=#{id} and password=#{pwd} </select>
3.Map参数绑定
import java.util.Map; public interface UserDao { //添加Map进行参数绑定 public User selectUserByIdAndPwd_map(Map values); } <select id="selectUserByIdAndPwd_map" resultType="user"> select*from t_users where id=#{myId} and password=#{pwdPwd}0 <!--通过key获取value--> </select>
4.对象参数绑定
public interface UserDao { //添加对象进行参数绑定 public User selectUserByUserInfo(User user); } <select id="selectUserByUserInfo" resultType="user"> select*from t_users where id=#{id} and password=#{password} <!--#{id}取User对象的id属性值、#{password 同理 --> </select>
5.模糊查询
public interface UserDao { public List<User> selectUserByLike(@Param("keyword") String keyword); } <mapper namespace="user"> <select id="selectUserByLike" resultType="user"> select*from t_users where name like concat('%',#{keyword},'%') </select> </mapper>
删除
标签:<delete id=" " parameterType=" ">
<delete id="deleteUser" resultType="int"> delete from t_users where id=#{id} <!--只有一个参数时任意书写--> </delete>
修改
标签:<update id=" " parameterType=" ">
<update id="updateUser" resultType="user"> update t_users set name=#{name}, password=#{password},sex=#{sex} where id=#{id} <!--方法参数为对象时,可直接使用#{属性名}进行获取--> </update>
添加
标签:<insert id=" " parameterType=" ">
<!-- 手动主键--> <insert id="insertUser" parameterType="user"> insert into t_users values (#{id},#{name},#{password},#{sex},null); </insert> <!-- 自动主键--> <insert id="insertUser" parameterType="user"> insert into t_users values (NULL,#{name},#{password},#{sex},null); </insert>
主键回填
标签: < selectKey id="" parameterType="" order="AFTER]BEFORE">
1.通过last_insert_id()查询主键
create table product( id int primary key auto_increment, name varchar(50) )default charset=utf8; calss Product( private Integer id; private String name; //set+get ); <mapper namespace="ProductDao"> <insert id="insertProuct" parameterType="product"> <selectKey keyProperty="id" resultType="int" order="AFTER"> <!--插入之后--> select LAST_INSERT_ID() <!--适用于整数类型自增--> </selectKey> insert into product(id,name)alues(#{id},#{name}) </insert> </mapper>
2.通过uuid()查询主键
create table order( id varchar(32) primary key, name varchar(50) )default charset=utf8; calss Order( private Integer id; private String name; //set+get ); <mapper namespace="OrderDao"> <insert id="insertOrder" parameterType="order"> <selectKey keyProperty="id" resultType="int" order="BEFFORE"> <!--插入之前--> select REPLACE(UUID(),'-','') <!--适用于字符类型主增--> </selectKey> insert into order(id,name)alues(#{id},#{name}) </insert> </mapper>
MyBatis工具类【重点】
封装工具类
Resource: 用于获得读取配置文件的10对象,耗费资源,建议通过10一次性读取所有所需要的数据。
SqlSessionFactory: SalSession工厂类,内存占用多,耗费资源,建议每个应用只创建一个对象。
SalSession: 相当于Connection,可控制事务,应为线程私有,不被多线程共享。将获得连接、关闭连接、提交事务、回滚事务、获得接口实现类等方法进行封装。
import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import java.io.IOException; import java.io.InputStream; public class SqlSessionUtil { //获取SqlSession工厂 private static SqlSessionFactory factory; //创建ThreadLocal绑定当前线程中的SqlSession对象 private static final ThreadLocal<SqlSession> tl=new ThreadLocal<SqlSession>(); static { try { InputStream is= Resources.getResourceAsStream("mybatis-config.xml"); } catch (IOException e) { throw new RuntimeException(e); } } //获取连接(从tl中获取当前线程SqlSession) private static SqlSession openSession(){ SqlSession session = tl.get(); if (session==null){ session = factory.openSession(); tl.set(session); } return session; } //释放链接(释放当前线程中的SqlSession) private static void closeSession(){ SqlSession session = tl.get(); session.close(); tl.remove(); } //提交事务(提交当前线程的SqlSession所管理的事务) private static void commit(){ SqlSession session=openSession(); session.commit(); closeSession(); } //回滚事务(回滚当前线程的SqlSession所管理的事务) private static void rollback(){ SqlSession session=openSession(); session.rollback(); closeSession(); } //获得接口实现类对象 public static <T extends Object>T getMapper(Class<T> tClass) { // 获取当前线程的SqlSession对象 SqlSession session = openSession(); return session.getMapper(tClass); } }
测试工具类
调用MyBatis中的封装方法。
@Test public woid testutils() ( try { UserDao userDao = MyBatisUtils.getMapper(UserDao.class); userDao .deleteUser(15); MyBatisUtils.commit(); }catch (Exception e) { MyBatisUtils.rollback(); e.printStackTrace(); } }
ORM隐射【重点】
MyBatis自动ORM失效
MyBatis只能自动维护库表”列名“与”属性名“相同时的一一对应关系,二者不同时,无法自动ORM。
方案一:列的别名
在SQL中使用 as 为查询字段添加列别名,以匹配属性名
<mapper namespace=ManagerDao"> <select id="selectManagerByIdAndPwd resultType="com.qf.mybatis.part2.orm.Manager"> SELECT mgr_id AS id , mgr_name AS username , mgr_pwd AS passwordFROM t_managersWHERE mgr_id = #{id} AND mgr_pwd = #{pwd} </select> </mapper>
方案二:结果隐射
通过< resultMap id=""type="">映射,匹配列名与属性名
<mapper namespace="ManagerDao"> <!--定义resultMap标签--> <resultMap id="managerResultMap" type="Manager"> <!--关联主键与列名--> <id property="id” column="mgr_id” /> <!--关联属性与列名--> <result property="username" column="mgr_name" /> <result property="password” column="mgr_pwd” /> </resultMap> <!--使用resultMap作为ORM映射依据--> <select id="selectAllManagers" resultMap="managerResultMap"> SELECT mgr_id , mgr_name , mgr_pwdFROM t_managers </select> </mapper>
MyBatis处理关联关系-多表连接【重点】
实体间的关系: 关联关系 (拥有 has、属于 belong)
OneToOne: 一对一关系 (Passenger--- Passport)
OneToMany:一对多关系 (Employee--- Department)ManyToMany: 多对多关系 (Student --- Subject)
OneToOne
sql参考OneToOneExample.sql
注意: 指定“一方”关系时 (对象),使用<association javaType="">
OneToMap
sql参考OneToManyExample.sql
注意: 指定“多方”关系时 (集合),使用< collection ofType="">
ManyToMap
sql参考OneToManyExample.sql
注意: 指定“多方”关系时 (集合),使用< collection ofType="">
关系总结
一方,添加集合;多方,添加对象。
双方均可建立关系属性,建立关系属性后,对应的Mapper文件中需使用 ResultMap>完成多表映射。持有对象关系属性,使用< association property="dept”javaType="department">
持有集合关系属性,使用< collection property="emps" ofType-"employee">
动态SQL[重点]
MyBatis的映射文件中支持在基础SQL上添加一些逻辑操作,并动态拼接成完整的SOL之后再执行,以达到SOL复用、简化编程的效果。
<sql>
<mapper namespace="user">
<sql id="Books_Field">
selecct id,name,author,sort
</sql>
<select id="selectBookByCondition" resultType="Book">
<include refid="Books_Field"/>
from t_books
</select>
</mapper>
<if>
<mapper namespace="user">
<sql id="Books_Field">
selecct id,name,author,sort
</sql>
<select id="selectBookByCondition" resultType="Book">
<include refid="Books_Field"/>
from t_books
<if test="name!=null">
name=#{name}
</if>
<if test="author!=null">
and author=#{author}
</if>
</select>
</mapper>
<where>
<select id="selectBookByCondition" resultType="Book">
select id,name,author,publish,sort from t_books
<where>
<if test="id!=null">
id=#{id}
</if>
<if test="name!=null">
name=#{name}
</if>
<if test="author!=null">
and author=#{author}
</if>
</where>
</select>
<set>
<update id="update t_books" >
update t_books
<set>
<if test="name!=null">
name=#{name}
</if>
<if test="author!=null">
author=#{author}
</if>
<if test="publish!=null">
publish=#{publish}
</if>
<if test="sort!=null">
sort=#{sort}
</if>
</set>
where id=#{id}
</update>
<trim>
<trim prefix="" suffix-"" prefixOverrides="" suffixOverrides="" >代替< where >、<set >
<foreach>
参数 | 描述 | 取值 |
collection | 容器类型 | list,array,map |
open | 起始符 | ( |
close | 结束符 | ) |
seoarator | 分隔符 | , |
index | 下标号 | 从0开始,依次递增 |
item | 当前项 | 任意名称 (循环中通过 #{任意名称}表达式访问) |
缓存(Cache)[重点]
内存中的一块存储空间,服务于某个应用程序,旨在将频繁读取的数据临时保存在内存中,便于二次快速访问。
一级缓存
SqlSession级别的缓存,同一个SqlSession的发起多次同构查询,会将数据保存在一级缓存中。
注意:无需任何配置,默认开启一级缓存
二级缓存
SalSessionFactor级别的缓存,同一个SalSessionFactory构建的SaSessin发起的多次同构查询,会将数据保存在二级缓存中。
注意: 在sqlSession.commit()或者sqlSession.close()之后生效
1.开启全局缓存
<settings >是MyBatis中极为重要的调整设置,他们会改变MyBatis的运行行为,其他详细配置可参考官方文档。
2.指定Mapper缓存
3.缓存清空并重新缓存
Druid连接池
简介
Druid 是阿里巴巴开源平台上的一个项目,整个项目由数据库连接池、插件框架和 SOL解析器组成。该项目主要是为了扩展JDBC的·些限制,可以让程序员实现一些特殊的需求,比如向密钥服务请求凭证、统计 SOL信息、SOL性能收集、SOL 注入检查、SOL 翻译等,程序员可以通过定制来实现自己需要的功能。
不同连接池对比
1.测试环境
环境 版本 os OS X 10.8.2 CPU Intel i7 2GHz 4 Core JVM Java Version 1.7.0_05 2.基准测试结果对比
JDBC-Conn Pool 1 Thread 2 threads 5 threads 10 threads 20 threads 50 threads Druid 898 1,191 1,324 1,362 1,325 1,459 tomcat-jdbc 1,200 1,378 2,029 2,103 1,879 2,025 DBCP 2,324 5,055 5,446 5,471 5,524 5,415 BoneCP 3,738 3,150 3,194 5,681 11,018 23,125 jboss-datasoure 4,377 2,988 3,6800 3,9800 32,708 37,742 C3p0 10,841 13,637 10,682 11,055 14,497 20,351 Proxool 15,337 16,187 18,310(Ex) 25,945 33,706(Ex) 39,501(Ex) 3.测试结论
Druid 是性能最好的数据库连接池,tomcatjdbc 和 druid 性能接近
Proxool在激烈并发时会抛异常,不适用。
C3PO 和Proxool 都相当慢,影响 sal 执行效率。
BoneCP 性能并不优越,采用 LinkedTransferQueue 并没有能够获得性能提升除了 bonecp,其他的在 JDK7上跑得比 JDK6上快。中jboss-datasource 虽然稳定,但性能很糟糕。
配置pom.xml
创建DruidDataSourceFactory
修改mybatis-vonfig.xml
PageHelper
简介
PageHelper是适用于MyBatis框架的一个分页插件,使用方式极为便捷,支持任何复杂的单表、多表分页查询操作。
访问与下载
开发步骤
1.引入依赖
2.配置MyBatis-config.xml
3.PageHelper应用方式
PageInfo对象
1.PageInfo应用方式
2.注意事项
只有在PageHelper.startPage()方法之后的第一个查询会有执行分页。
分页插件 不支持带有“for update”的查询语句。
分页插件不支持“嵌套查询”,由于嵌套结果方式会导致结果集被折叠,所以无法保证分页结果数量正确。3.分页练习
使用Servlet+jsp+MyBatis+分页插件,完成分页查询功能。