MyBatis01
框架概述
什么是框架及优势
- 框架(Framework)是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方法;另一种定义认为,框架是可被应用开发者定制的应用骨架。前者是从应用方面而后者是从目的方面给出的定义。
- 框架其实就是某种应用的半成品,就是一组组件,供你选用完成你自己的系统。简单说就是使用别人搭好的舞台,你来做表演。而且,框架一般是成熟的,不断升级的软件。
- 由于效率和易用性的考虑使用框架。框架能节省开发时间。框架强制使用公共的约定,因此它能有效地解决一些共有的问题,它能让决定更连贯,避免写一大堆自定义模块来实现这些性能,框架节省了不少的时间和精力,并且让扩展变得更容易。
框架解决的问题
-
技术整合
- 框架要解决的最重要的一个问题是技术整合的问题,在 J2EE 的 框架中,有着各种各样的技术,不同的软件企业需要从 J2EE 中选择不同的技术,这就使得软件企业最终的应用依赖于这些技术,技术自身的复杂性和技术的风险性将会直接对应用造成冲击。而应用是软件企业的核心,是竞争力的关键所在,因此应该将应用自身的设计和具体的实现技术解耦(高内聚 低耦合)。这样,软件企业的研发将集中在应用的设计上,而不是具体的技术实现,技术实现是应用的底层支撑,它不应该直接对应用产生影响。框架一般处在低层应用平台(如 J2EE )和高层业务逻辑之间的中间层。
-
三层架构
- 框架的重要性在于它实现了部分功能,并且能够很好的将低层应用平台和高层业务逻辑进行了缓和。为了实现软件工程中的“高内聚、低耦合”。把问题划分开来各个解决,易于控制,易于延展,易于分配资源。我们常见的MVC软件设计思想就是很好的分层思想。javabean+servlet+jsp(html)
- 框架的重要性在于它实现了部分功能,并且能够很好的将低层应用平台和高层业务逻辑进行了缓和。为了实现软件工程中的“高内聚、低耦合”。把问题划分开来各个解决,易于控制,易于延展,易于分配资源。我们常见的MVC 软件设计思想就是很好的分层思想
- 三层架构就是为了符合“高内聚,低耦合”思想,把各个功能模块划分为表示层(UI)、业务逻辑层(BLL)和数据访问层(DAL)三层架构,各层之间采用接口相互访问,并通过对象模型的实体类(Model)作为数据传递的载体,不同的对象模型的实体类一般对应于数据库的不同表,实体类的属性与数据库表的字段名一致。“高内聚,低耦合”,可以使开发人员分工更明确,将精力更专注于应用系统核心业务逻辑的分析、设计和开发,加快项目的进度,提高了开发效率,有利于项目的更新和维护工作。
-
分层后优势
- 1.避免了表示层直接访问数据访问层,表示层只和业务逻辑层有联系,提高了数据安全性。
- 2.有利于系统的分散开发,每一个层可以由不同的人员来开发,只要遵循接口标准,利用相同的对象模型实体类就可以了,这样就可以 大大提高系统的开发速度。
- 3.方便系统的移植,如果要把一个 C/S 的系统变成 B/S 系统,只要修改三层架构的表示层就可以了,业务逻辑层和数据访问层几乎 不用修改就可以轻松的把系统移植到网络上。
- 4.项目结构更清楚,分工更明确,有利于后期的维护和升级。
-
三层架构体系
- 表示层(表现层 视图层):和客户端进行交互的技术的统称(mvc思想的框架都是表示层技术)
- 业务逻辑层:协调表示层和数据访问层的之间的业务处理关系
- 数据访问层: 实体对象在数据库中进行持久化
-
持久层技术解决方案
-
jdbc技术是jdk的原生API,提供对数据进行持久化底层技术,是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新数据库中数据的方法。
-
Commons DbUtils是Apache组织提供的一个对JDBC进行简单封装的开源工具类库,使用它能够简化JDBC应用程序的开发,同时也不会影响程序的性能,同时内置事务自动提交。
-
jdbc做为持久层技术存在的问题(mybaits)。
-
- 数据库连接创建、释放频繁造成系统资源浪费,从而影响系统性能。
jdbc: 耗费资源
- 数据库连接创建、释放频繁造成系统资源浪费,从而影响系统性能。
-
- Sql语句在代码中硬编码,造成代码不易维护,实际应用中sql变化的可能较大,sql变动需要改变java代码。
-
- 使用preparedStatement向占有位符号传参数存在硬编码,因为sql语句的where条件不一定,可能多也可能少,修改sql还要修改代码,系统不易维护。
动态的拼接sql语句不灵活
- 使用preparedStatement向占有位符号传参数存在硬编码,因为sql语句的where条件不一定,可能多也可能少,修改sql还要修改代码,系统不易维护。
-
- 对结果集解析存在硬编码(查询列名),sql变化导致解析代码变化,系统不易维护,如果能将数据库记录封装成pojo对(javaBean)解析比较方便。
代码书写完毕以后,我们根据业务需求修改表或者是修改表对应的数据模型都会导致原有的程序出现问题
- 对结果集解析存在硬编码(查询列名),sql变化导致解析代码变化,系统不易维护,如果能将数据库记录封装成pojo对(javaBean)解析比较方便。
-
- 代码冗余太大,sql与Java程序耦合太紧密,不利于sql维护。
-
-
常见框架
-
持久化框架
- 持久化框架Mybatis(SSM)
Spring+SpringMVC+MyBatis(互联网项目) - 持久化框架Hibernate (SSH)
Spring+Struts+Hibernate(传统项目 ERP OA )
- 持久化框架Mybatis(SSM)
-
web层MVC思想框架
- Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面。Spring 框架提供了构建 Web 应用程序的全功能MVC模块。使用 Spring 可插入的 MVC 架构,从而在使用Spring进行WEB开发时,可以选择使用Spring的SpringMVC框架或集成其他MVC开发框架,如Struts1(现在一般不用),Struts 2(一般老项目使用)等等
-
技术整合框架
- Spring是Java EE编程领域的一个轻量级开源框架,该框架由一个叫Rod Johnson的程序员在 2002 年最早提出并随后创建,是为了解决企业级编程开发中的复杂性,实现敏捷开发的应用型框架 。Spring是一个开源容器框架,它集成各类型的工具,通过核心的Bean factory实现了底层的类的实例化和生命周期的管理。在整个框架中,各类型的功能被抽象成一个个的 Bean,这样就可以实现各种功能的管理,包括动态加载和切面编程。
Mybatis概述
mybatis简介
- mybatis是一个优秀的基于 java 的持久层框架,它内部封装了jdbc,使开发者只需要关注 sql 语句本身,而不需要花费精力去处理加载驱动、创建连接、创建 statement 等繁杂的过程。
- mybatis通过xml或注解的方式将要执行的各种statement配置起来,并通过java对象和statement中sql 的动态参数进行映射生成最终执行的sql语句,最后由 mybatis 框架执行sql并将结果映射为 java 对象并返回。
- 采用ORM思想解决了实体和数据库映射的问题,对jdbc进行了封装,屏蔽了jdbc api底层访问细节,使我们不用与jdbc api打交道,就可以完成对数据库的持久化操作。
mybatis的特点
- (1) 简单易学:本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件易于学习,易于使用通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
- (2) 灵活:mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql语句可以满足操作数据库的所有需求。
- (3) 解除sql与程序代码的耦合:通过提供DAO层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。
- (4) 提供映射标签,支持对象与数据库的orm字段关系映射。
- (5) 提供对象关系映射标签,支持对象关系组建维护。
- (6) 提供xml标签,支持编写动态sql。
- (7) 支持数据缓存和注解开发。
Mybatis环境搭建
前期准备
- 创建数据库
- 创建maven项目
- 导入依赖
搭建项目环境
- 编写User实体类
- 编写映射文件UserDao.xml
- 编写mybatis主配置文件SqlMapConfig.xml
MyBatis基于代理Dao实现CRUD操作(重点)
定义接口
package com.offcn.mapper;
import com.offcn.bean.User;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
/**
* @author: ChengLong
* @version: 11.0.2
* @datetime: 2021/9/13 19:48
*/
public interface UserMapper {
public List<User> showAllInfo();
public int deleteInfo(Integer id);
public int addInfo(User user);
public int updateInfo(User user);
//模糊查询
public List<User> getInfoLikeName(String name);
//测试接口方法中存在多个参数
public List<User> moreArgsTest(User user);
public List<User> moreArgsTest1(@Param("name") String name, @Param("age") Integer age);
public List<User> moreArgsTest2(Map<String,Object> map);
}
配置映射文件
<?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">
<!--如果执行的是查询操作,当前标签必须添加resultType,所有的数据操作标签中parameterType可以省略-->
<mapper namespace="com.offcn.mapper.UserMapper">
<!-- 配置查询的sql语句-->
<select id="showAllInfo" resultType="User">
select * from user
</select>
<!-- #{} 占位符中的变量名可以自定义-->
<delete id="deleteInfo" parameterType="int">
delete from user where id=#{id}
</delete>
<!--标签的名称和我们操作数据动作要匹配
id:必须和接口种方法的名称对应
#{} mybatis代表sql语句种的占位符
我们传入参数是自定义对象:所以占位符变量名称必须是我们传入参数类型的属性名称
-->
<insert id="addInfo" parameterType="user">
insert into user(id,name,gender,age,birthday) values(#{id},#{name},#{gender},#{age},#{birthday})
</insert>
<update id="updateInfo" parameterType="user">
update user set name=#{name},age=#{age} where id=#{id}
</update>
</mapper>
配置文件
<?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>
<typeAliases>
<!-- <typeAlias type="com.offcn.bean.User" alias="user"></typeAlias>-->
<!-- 扫描包的形式设置别名 那么在***Mapper.xml配置文件中使用别名 (类名\类名的首字母小写形式)-->
<package name="com.offcn.bean"/>
</typeAliases>
<environments default="mysqlInfo">
<environment id="mysqlInfo">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="username" value="root"/>
<property name="password" value="1s2h3a4o56789"/>
<property name="url" value="jdbc:mysql://192.168.196.181:3306/user"/>
<property name="driver" value="com.mysql.jdbc.Driver"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="UserMapper.xml"></mapper>
</mappers>
</configuration>
测试方法
package com.offcn.test;
import com.offcn.bean.User;
import com.offcn.mapper.UserMapper;
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.junit.Test;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author: ChengLong
* @version: 11.0.2
* @datetime: 2021/9/13 19:20
*/
public class MybatisTest {
@Test
public void test() throws Exception{
/*
* 1.读取主配置文件 mybatis-config.xml
* 2.SqlSessionFactory mybatis提供工具类
* 3.SqlSession 操作sql配置
* 4.sqlsession调用sql及进行通信
* */
String path = "mybatis-config.xml";
InputStream resourceAsStream = Resources.getResourceAsStream(path);
//构建工厂
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
//创建Sqlsession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//为接口创建对象
/*
* UserMapper接口类型
* mybatis利用了反射还有java动态代理设计模式
* 创建了接口的代理对象
* */
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//当前对象mapper不是接口的实现类对象,是java通过动态代理创建代理对象(操作数据库过程中不需要手动添加事务管理代码)
//查询
List<User> list = mapper.showAllInfo();
System.out.println(list);
//删除
// mapper.deleteInfo(2);
User user = new User(4,"admin","man",34,new java.util.Date());
//增加
mapper.addInfo(user);
//修改
mapper.updateInfo(user);
//事务操作 最后需提交
sqlSession.commit();
Mybatis执行原理分析
配置文件分析
-
核心配置文件
<?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> <!-- 配置 mybatis 的环境 --> <environments default="development"> <!-- 配置的环境 --> <environment id="development"> <!-- 配置事务的类型 --> <transactionManager type="JDBC"></transactionManager> <!-- 配置连接数据库的信息:用的是数据源【连接池)】--> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis001"/> <property name="username" value="root"/> <property name="password" value="root"/> </dataSource> </environment> </environments> <!-- 注册UserDao接品映射文件位置 --> <mappers> <mapper resource="cn/offcn/dao/UserDao.xml"/> </mappers> </configuration> 核心配置文件参数详解: (1)environment标签中的id属性值必须和environments标签中的default属性一致。 (2)事务管理器: 第一种采用JDBC事务类型,直接使用了 JDBC的提交和回滚设施,它依赖从数据源获得的连接来管理事务作用域。 第二种采用MANAGED事务类型,它从不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。默认情况下它会关闭连接。然而一些容器并不希望连接被关闭,因此需要将 closeConnection 属性设置为 false 来阻止默认的关闭行为。例如: <transactionManager type="MANAGED"> <property name="closeConnection" value="false"/> </transactionManager> (3) 数据源(dataSource) dataSource元素使用标准的JDBC数据源接口来配置JDBC连接对象的资源。大多数 MyBatis 应用程序会按示例中的例子来配置数据源。 虽然数据源配置是可选的,但如果要启用延迟加载特性,就必须配置数据源。 有三种内建的数据源类型(也就是 type="[UNPOOLED|POOLED|JNDI]") UNPOOLED– 这个数据源的实现会每次请求时打开和关闭连接。虽然有点慢,但对那些数据库连接可用性要求不高的简单应用程序来说,是一个很好的选择。 性能表现则依赖于使用的数据库,对某些数据库来说,使用连接池并不重要,这个配置就很适合这种情形。 POOLED– 这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来,避免了创建新的连接实例时所必需的初始化和认证时间。 这种处理方式很流行,能使并发 Web 应用快速响应请求。 JNDI – 这个数据源实现是为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个JNDI上下文的数据源引用。 (5) mapper中的resource属性用于指定映射文件的位置。mapper中有多个属性可以描述映射文件,分别为: resource=“cn/offcn/dao/UserDao.xml” 文件在多级目录中要用分隔符“/”隔开。 class="cn.offcn.dao.UserDao" 指定UserDao接口文件位置,但此时UserDao.xml必须和接口处在同一个包中并且文件名要相同。 -
映射文件
<mapper namespace="cn.offcn.dao.UserDao"> <!--配置查询的sql语句--> <select id="queryAllUsers" resultType="cn.offcn.entity.User"> select * from user </select> </mapper> 映射文件参数详解: (1) namespace必须为接口的完全限定名(即包名+类名的格式)。 (2) select标签中的id必须和接口中声明的方法同名。 (3) 如果接口中方法有返回值,resyultType必须跟方法返回值一致并采用返回值的完全限定名来表示。
#{} PreparedStatement和${} Statement的区别
#{}是预编译处理,${}是字符串替换(静态sql)。
Mybatis在处理${变量名}时,就是把${变量名}替换成变量的值。 将值拼接到sql语句中
Mybatis在处理#{}时,会将 sql 中的#{}替换为?号,调用 PreparedStatement 的 set 方法来赋值
使用#{}可以有效的防止 SQL 注入,提高系统安全性。${}字符串拼接存在sql注入风险
MyBatis实现模糊查询
-
添加模糊查询的接口方法
//模糊查询 public List<User> getInfoLikeName(String name); -
配置接口方法对应的sql文件
<!-- 模糊查询--> <select id="getInfoLikeName" parameterType="User"> --配置占位符方式#{} -- select * from user where name like '#{name}' -- 配置拼接字符串方式${} -- select * from user where name like '%${name}%' -- 后续使用此方式模糊查询 配置mysql函数方式concat select * from user where name like concat('%',#{name},'%') </select> -
模糊查询测试
package com.offcn.test; import com.offcn.bean.User; import com.offcn.mapper.UserMapper; 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.junit.Test; import java.io.InputStream; import java.util.HashMap; import java.util.List; import java.util.Map; /** * @author: ChengLong * @version: 11.0.2 * @datetime: 2021/9/13 19:20 */ public class MybatisTest { @Test public void test() throws Exception{ /* * 1.读取主配置文件 mybatis-config.xml * 2.SqlSessionFactory mybatis提供工具类 * 3.SqlSession 操作sql配置 * 4.sqlsession调用sql及进行通信 * */ String path = "mybatis-config.xml"; InputStream resourceAsStream = Resources.getResourceAsStream(path); //构建工厂 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream); //创建Sqlsession对象 SqlSession sqlSession = sqlSessionFactory.openSession(); //为接口创建对象 /* * UserMapper接口类型 * mybatis利用了反射还有java动态代理设计模式 * 创建了接口的代理对象 * */ UserMapper mapper = sqlSession.getMapper(UserMapper.class); //模糊查询 mapper.getInfoLikeName("admin");
MyBatis的多个参数处理
接口方法
- 传入参数是一个定义的 java对象 然后在sql语句中使用对象的属性名称
- 在定义方法的时候使用@Param注解声明在sql语句中使用的变量的名称
- 传入参数是一个map集合,然后在sql语句中使用map集合的key值
- 使用接口方法参数的默认的顺序 param1 param2 arg0 arg1 ....
//测试接口方法中存在多个参数
public List<User> moreArgsTest(User user);
public List<User> moreArgsTest1(@Param("name") String name, @Param("age") Integer age);
public List<User> moreArgsTest2(Map<String,Object> map);
配置文件内容
<!-- 多个参数测试 -->
<select id="moreArgsTest" resultType="User">
select * from user where name=#{name} and age=#{age}
</select>
<select id="moreArgsTest1" resultType="User">
select * from user where name=#{name} and age=#{age}
<!--
select * from user where name=#{param1} and age=#{param2}
select * from user where name=#{arg0} and age=#{arg1}
-->
</select>
<select id="moreArgsTest2" resultType="User">
<!-- 我们在sql中使用变量的名称就是map集合中key的名字 -->
select * from user where name=#{uname} and age=#{uage}
</select>
测试方法
package com.offcn.test;
import com.offcn.bean.User;
import com.offcn.mapper.UserMapper;
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.junit.Test;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author: ChengLong
* @version: 11.0.2
* @datetime: 2021/9/13 19:20
*/
public class MybatisTest {
@Test
public void test() throws Exception{
/*
* 1.读取主配置文件 mybatis-config.xml
* 2.SqlSessionFactory mybatis提供工具类
* 3.SqlSession 操作sql配置
* 4.sqlsession调用sql及进行通信
* */
String path = "mybatis-config.xml";
InputStream resourceAsStream = Resources.getResourceAsStream(path);
//构建工厂
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
//创建Sqlsession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//为接口创建对象
/*
* UserMapper接口类型
* mybatis利用了反射还有java动态代理设计模式
* 创建了接口的代理对象
* */
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//多参
//mapper.moreArgsTest(user);
//mapper.moreArgsTest1("admin",34);
Map<String,Object> map = new HashMap<>();
map.put("uname","admin");
map.put("uage",23);
mapper.moreArgsTest2(map);
}
}

浙公网安备 33010602011771号