mybatis入门案例分析
mybatis入门案例分析
一、设计模式分析
public class MybatisTest {
public static void main(String[] args) throws Exception{
//1.读取配置文件
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
//3.使用工厂生产SqlSession对象
SqlSession session = factory.openSession();
//4.使用SqlSession创建Dao的代理对象
IUserDao userDao = session.getMapper(IUserDao.class);
//5.使用代理对象执行方法
List<User> users = userDao.findAll();
for(User user : users) {
System.out.println(user);
}
//6.释放资源
session.close();
in.close();
}
}
1.读取配置文件
在读取文件时,通常有两种方法,一种是采用绝对路径,另一种是采用相对路径。如果采用绝对路径,其缺点为不易迁移和部署,在开发时如果我们路径为“D:\SqlMapConfig.xml”,部署到服务器时,可能服务器上没有D盘。相对路径的缺点就在于,如果项目为Web工程,部署之后src目录就不存在了。因此在读取配置文件时,只有两种方法:
1.使用类加载器:只能读取类路径的配置文件。
2.使用SeverletContext对象的getPath()方法。
2.创建工厂
在创建工厂时,mybatis使用了构建者模式,builder就是构建者,把对象的创建细节隐藏,使用户直接调用方法便可获得对象。
3.生产SqlSession对象
生产SqlSession对象时使用了工厂模式,可以降低类间的依赖关系,便于之后对项目进行修改。
4.创建代理对象
创建DAO接口实现类的代理对象实现了使用了代理模式,这样就不需要自己写DAO实现类。
二、mybatis执行查询所有的分析
1.普通的java实现数据库查询
1.注册驱动,获取connection对象
2.创建数据库的执行sql的预处理对象
3.执行sql语句
4.封装查询结果
5.释放资源
public class JDBCTest {
public static void main(String[] args) {
JDBCTest test=new JDBCTest();
test.firstJDBC();
}
public void firstJDBC(){
Connection connection=null;
PrepareStatement prepareStatement=null;
ResultSet resultSet=null;
try {
//1.register,注册驱动
DriverManager.registerDriver(new Driver());
//2.得到数据连接。url格式:jdbc:mysql://主机IP:端口号/数据库名?user=用户名&password=密码
//因为MySQL安装时,端口号默认设置的是3306,所以都是3306
String url="jdbc:mysql://localhost:3306/sport?user=root&password=12345678";
connection=DriverManager.getConnection(url);
//3.得到数据库的执行sql对象
String sql="select * from player"; //SQL查询语句
prepareStatement=connection.prepareStatement();
//4.执行语句
resultSet=prepareStatement.executeQuery();
while(resultSet.next()){
//取出查询的信息
String name=resultSet.getString("player_name");
int age=resultSet.getInt("player_age");
int score=resultSet.getInt("player_score");
System.out.println("name="+name+",age="+age+",score="+score);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
//5.关闭资源
if(connection!=null){
try {
connection.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(prepareStatement!=null){
try {
prepareStatement.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(resultSet!=null){
try {
resultSet.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
2.mybatis中如何实现查询
<!-- mybatis的主配置文件 -->
<configuration>
<!-- 配置环境 -->
<environments default="mysql">
<!-- 配置mysql的环境 -->
<environment id="mysql">
<!-- 配置事务的类型 -->
<transactionManager type="JDBC"></transactionManager>
<!-- 配置数据源(连接池) -->
<dataSource type="POOLED">
<!-- 配置连接数据库的四个基本信息 -->
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
<property name="username" value="root"/>
<property name="password" value="12345678"/>
</dataSource>
</environment>
</environments>
<!-- 指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件 -->
<mappers>
<mapper resource="dao/IUserDao.xml" />
</mappers>
</configuration>
1.创建connection对象。通过主被配置文件SqlMapConfig.xml,我们可以获得连接数据库的信息(驱动、路径、用户名和密码)以及映射配置文件的位置。通过连接数据库的信息,我们可以构建connection对象。
<mapper namespace="dao.IUserDao">
<!-- 配置查询所有 -->
<select id="findAll" resultType="domain.User">
select * from user;
</select>
</mapper>
2.创建prepareStatement对象。通过映射配置文件的信息,我们可以获得执行的SQL语句和封装的实体类全限定类名,就可以创建prepareStatement对象。mybatis通过dom4j技术来解析xml文件获取上述信息。
3.存储解析结果。在获取相关信息中后,mybatis需要将执行的SQL语句和封装结果的实体类全限定类名组合起来定义成一个Mapper对象,每一个Mapper对象对应一个完整String类型的id(namespace+“.”+id)。例如本项目中的SQL语句为“select * from user;”,封装结果的实体类全限定类名为“domain.user”,完整的id为"dao.IUserDao.findAll",这些都是String类型的字段。
4.利用反射技术封装。创建prePareStatement对象之后,通过resultSet = prepareStatement.executeQuery();语句我们可以获得查询结果集,在对查询结果集进行封装时。我们通过完整的id(即封装结果的全限定类名),利用反射技术(Class.forName("domain.User").getDeclaredConstructor().newInstance();)即可进行封装。由于实体类的属性和数据库表中的列名一致,可以把表的列名当作是实体类的属性名称,然后利用反射技术来根据名称获取每个属性,并把值赋进去。反射参考链接。
三、创建代理对象的分析
//MybatisTest.class
IUserDao userDao = session.getMapper(IUserDao.class);
//DefaultSqlSession.class
public <T> T getMapper(Class<T> type) {
return this.configuration.getMapper(type, this);
}
//Configuration.class
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
return this.mapperRegistry.getMapper(type, sqlSession);
}
//MapperRegistry.class
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory)this.knownMappers.get(type);
if (mapperProxyFactory == null) {
throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
} else {
try {
return mapperProxyFactory.newInstance(sqlSession);
} catch (Exception var5) {
throw new BindingException("Error getting mapper instance. Cause: " + var5, var5);
}
}
}
//MapperProxyFactory.class
public T newInstance(SqlSession sqlSession) {
MapperProxy<T> mapperProxy = new MapperProxy(sqlSession, this.mapperInterface, this.methodCache);
return this.newInstance(mapperProxy);
}
protected T newInstance(MapperProxy<T> mapperProxy) {
return Proxy.newProxyInstance(this.mapperInterface.getClassLoader(), new Class[]{this.mapperInterface}, mapperProxy);
}
//Proxy.class
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,
InvocationHandler h) {
Objects.requireNonNull(h);
final Class<?> caller = System.getSecurityManager() == null
? null
: Reflection.getCallerClass();
/*
* Look up or generate the designated proxy class and its constructor.
*/
Constructor<?> cons = getProxyConstructor(caller, loader, interfaces);
return newProxyInstance(caller, cons, h);
}
上述是MybatisTest类中,getMapper()的调用层级。可以看到最终调用的方法是public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h),这个方法有三个参数,分别是:
1.类加载器loader:使用和被代理对象相同的类加载器
2.代理对象要实现的接口字节码数组interfaces:和被代理对象实现的是相同的接口
3.代理方式h:就是增强的方法,实际上就是一个InvocationHandler接口的实现类,在实现类中调用selectList方法(查询所有方法)。
mybatis入门案例,可以参考我的上一篇博客:mybatis入门实例
mybatis入门案例分析的更多相关文章
- mybatis入门案例自定义实现
mybatis入门案例自定义实现 一.需要实现的类和接口 public static void main(String[] args) throws Exception{ //1.读取配置文件 Inp ...
- Mybatis入门案例中设计模式的简单分析
Talk is cheap, show me the code! public class TestMybatis { public static void main(String[] args) t ...
- MyBatis入门案例、增删改查
一.MyBatis入门案例: ①:引入jar包 ②:创建实体类 Dept,并进行封装 ③ 在Src下创建大配置mybatis-config.xml <?xml version="1.0 ...
- MyBatis入门案例 增删改查
一.MyBatis入门案例: ①:引入jar包 ②:创建实体类 Dept,并进行封装 ③ 在Src下创建大配置mybatis-config.xml <?xml version="1.0 ...
- ArcGIS for Desktop入门教程_第四章_入门案例分析 - ArcGIS知乎-新一代ArcGIS问答社区
原文:ArcGIS for Desktop入门教程_第四章_入门案例分析 - ArcGIS知乎-新一代ArcGIS问答社区 1 入门案例分析 在第一章里,我们已经对ArcGIS系列软件的体系结构有了一 ...
- 03 Mybatis:01.Mybatis课程介绍及环境搭建&&02.Mybatis入门案例
mybatis框架共四天第一天:mybatis入门 mybatis的概述 mybatis的环境搭建 mybatis入门案例 -------------------------------------- ...
- spring入门案例分析及原理
Springmvc执行原理: 一. 入门案例的执行流程 1. 当启动Tomcat服务器的时候,因为配置了load-on-startup标签,所以会创建DispatcherServlet对象,就会加载s ...
- intellij IDEA Mybatis入门案例
最近打算学习ssm框架 Mybatis 作为入门的第一个持久层框架,学习起来实在费劲.故写此文章作为入门案例. 先打开 IDEA建立一个Maven项目,目录结构如下: 源代码已经上传至GitHub ...
- 一、mybatis入门案例
今天学习了mybatis框架,简单记录一下mybatis第一个入门案例,目标是使用Mybatis作为持久层框架,执行查询数据的SQL语句并且获取结果集 基本步骤: 物理建模 逻辑建模 引入依赖 创建持 ...
随机推荐
- eclipse中部署web项目时报错java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListener的解决方法
解决方案: 1.右键点击项目--选择Properties,选择Deployment Assembly,在右边点击Add按钮,在弹出的窗口中选择Java Build Path Entries 2.点击N ...
- IteratorPattern(迭代器模式)-----Java/.Net
迭代器模式(Iterator Pattern)是 Java 和 .Net 编程环境中非常常用的设计模式.这种模式用于顺序访问集合对象的元素,不需要知道集合对象的底层表示
- day2(使用list和tuple)
list list是一种有序的集合 >>>aaa = ['abc','bob','tracy'] >>>aaa ['abc','bob','tracy'] len( ...
- 文档对象DOM的操作及使用
Dom对象是什么? DOM对象就是每次你打开浏览器后,进入一个网址时浏览器获取到的HTML文本内容,当浏览器获取到HTML文本内容时,会将其内容以DOM对象的形式缓存到内存中,这时你便可以对DOM对象 ...
- Java String类相关知识梳理(含字符串常量池(String Pool)知识)
目录 1. String类是什么 1.1 定义 1.2 类结构 1.3 所在的包 2. String类的底层数据结构 3. 关于 intern() 方法(重点) 3.1 作用 3.2 字符串常量池(S ...
- ACM北大暑期课培训第三天
今天讲的内容是深搜和广搜 深搜(DFS) 从起点出发,走过的点要做标记,发现有没走过的点,就随意挑一个往前走,走不 了就回退,此种路径搜索策略就称为“深度优先搜索”,简称“深搜”. bool Dfs( ...
- 5、调试显示应该使用 DebuggerDisplay 而不是误用 ToString
using System.Diagnostics; namespace ShouldCode.Console { [DebuggerDisplay("Prop1:{Prop1};Prop2: ...
- 全网最详细的Linux命令系列-sed文本处理命令
Sed简介 SED是一个非交互式文本编辑器,它可对文本文件和标准输入进行编辑,标准输入可以来自键盘输入.文本重定向.字符串.变量,甚至来自于管道的文本,与VIM编辑器类似,它一次处理一行内容,Sed可 ...
- asp.net core 基于 JSON 实现多语言
asp.net core 基于 JSON 实现多语言 Intro 上次我们提到了,微软默认提供基于资源文件的多语言本地化,个人感觉使用起来不是太方便,没有 json 看起来直观,于是动手造了一个轮子, ...
- 关于程序员须知的 linux 基础
我在 github 上新建了一个仓库 日问,每天一道面试题,有关前端,后端,devops以及软技能,促进职业成长,敲开大厂之门,欢迎交流 并且记录我的面试经验 17年面试记(阿里百度美团头条小米滴滴) ...