DriverManager: 注册驱动
Connection: 数据库的连接
Statement: 执行SQL语句的对象(小货车)
ResultSet: 结果集
使用PreparedStatement对象解决SQL注入
先写SQL语句,不确定使用?占位,后面在给?赋值
连接池的优点: 避免频繁的创建和销毁连接,让连接可以重复使用,提高性能
能够了解什么是框架
掌握mybatis框架开发快速入门
理解自定义mybatis框架
mybatis_day01_01_helloworld 体验mybatis第1个项目
mybatis_day01_02_framework 自定义框架
学习项目的三层架构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VrkrUHEs-1597834865210)(分层00.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HBME0iLZ-1597834865229)(分层03.png)]
三层架构有哪三层?
我们在企业开发中为了提高开发效率会使用框架进行开发。什么是框架呢?
SSM框架
学习框架的概念
框架解决了哪些问题
之前我们都是根据需求写出所有的相关代码麻烦,累,繁琐。框架是别人写好的代码,是对常见功能的封装,是一个半成品。我们在框架的基础上开发出成品的软件。
假如你要造一辆马车,在没有零件的情况下,你需要自己去伐木,去把木头做成木板,木棍,然后做成轮子,门,等部件,然后组装起来,很麻烦。框架就相当于现成的轮子,门等部件。我们只需要拿过来使用即可。
常见框架如:Spring,SpringMVC,Mybatis,JdbcTemplate,Bootstrap, VUE等等。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8aPLpc7b-1597834865286)(1557575891993.png)]
企业项目中使用框架,程序员不再需要重复造轮子,只需要专注实现业务需求,提升了开发效率。
一个成熟的框架,经过了在众多企业项目中的验证使用,稳定性有保障。
在J2EE应用中,通常把项目整体进行分层设计。有表现层、业务层、持久层。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UuWFXXIv-1597834865287)(1557581801412.png)]
MyBatis是一款优秀的持久层框架,MyBatis 避免了几乎所有的 JDBC代码和手动设置参数以及获取结果集。
关于持久层的框架,还有一个封装程度更高的框架(hibernate)。该框架相对比较重量级,以及其它各个方面的原因,目前流行程度下降了很多,企业项目中用的越来越少了。
SpringMVC是一种基于Java,实现了Web MVC设计模式,将Web层进行解耦。SpringMVC可以简化我们日常Web开发。
Spring是一个轻量级控制反转(IoC)和面向切面(AOP)的容器框架。让开发变的更简单。
什么是框架?
别人写好的代码,对常用功能封装,是一个半成品
框架解决了哪些问题
MyBatis框架介绍
学习MyBatis下载
MyBatis是Apache软件基金会下的一个开源项目,前身是iBatis框架。2010年这个项目改名为MyBatis。是一个持久层框架
http://www.mybatis.org/mybatis-3/
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SS8unJXF-1597834865290)(1557582491118.png)]
连接到github地址:https://github.com/mybatis/mybatis-3/releases
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GmjHt1Er-1597834865293)(1557582590735.png)]
MyBatis框架哪一层框架?
持久层框架,简化JDBC对数据库的操作
了解MyBatis的开发步骤
MyBatis开发环境的搭建
利用MyBatis框架,从MySQL中查询所有的用户
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZSooXs4j-1597834865295)(1557583413350.png)]
CREATE TABLE USER (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(20) NOT NULL,
birthday DATE,
sex CHAR(1) DEFAULT '男',
address VARCHAR(50)
);
INSERT INTO USER VALUES (NULL, '孙悟空','1980-10-24','男','花果山水帘洞');
INSERT INTO USER VALUES (NULL, '白骨精','1992-11-12','女','白虎岭白骨洞');
INSERT INTO USER VALUES (NULL, '猪八戒','1983-05-20','男','福临山云栈洞');
INSERT INTO USER VALUES (NULL, '蜘蛛精','1995-03-22','女','盤丝洞');
SELECT * FROM USER;
创建模块:mybatis_day01_01_helloworld
加入MyBatis相关jar包:在模块下新建lib文件夹,复制mybatis框架jar包到lib文件夹下
MyBatis框架包
MySQL数据库驱动包
log4j 日志包
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yN7x9mjn-1597834865297)(/1562574926561.png)]
编写用户实体类(User)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ixfd7t5S-1597834865299)(/1564963745081.png)]
/**
用户实体类对象 */
public class User {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
// 省略构造方法/getter/setter/toString
}
#### 配置文件
复制log4j.properties到 src 下
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EKC3f97P-1597834865301)(/1564963930552.png)]
```properties
### 设置Logger输出级别和输出目的地 ###
log4j.rootLogger=debug, stdout
### 把日志信息输出到控制台 ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.SimpleLayout
MyBatis的环境搭建做了哪几件事情?
创建模块:mybatis_day01_01_helloworld
加入MyBatis相关jar包:在模块下新建lib文件夹,复制mybatis框架jar包到lib文件夹下
MyBatis框架包
MySQL数据库驱动包
log4j 日志包
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-P05ATxHP-1597834865304)(1562574926561.png)]
编写用户实体类(User类)
复制log4j.properties到 src下
MyBatis为了灵活,将数据库相关数据和SQL语句写到XML配置文件中。
编写核心配置文件:sqlMapConfig.xml
复制资料\01_mybatis框架模板\sqlMapConfig.xml到src下,说明:它是mybatis框架的核心配置文件,mybatis就是靠这些信息来运行的。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UfkUmC23-1597834865306)(/1564964116640.png)]
<configuration>
<environments default="default">
<environment id="default">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
dataSource>
environment>
environments>
<mappers>
<mapper resource="接口映射文件位置"/>
mappers>
configuration>
核心配置文件配置了4个参数:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zUgYpdf0-1597834865308)(/1564964046384.png)]
创建com.itheima.dao包,创建UserMapper接口。编写查询所有用户的方法:List
/**
定义DAO中方法
*/
public interface UserMapper {
/**
查询所有的用户
*/
List<User> findAllUsers();
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OJDdhgsY-1597834865309)(/1564964067707.png)]
在com.itheima.dao包中创建UserMapper.xml映射文件
<mapper namespace="com.itheima.dao.UserMapper">
<select id="findAllUsers" resultType="com.itheima.entity.User">
select * from user;
select>
mapper>
在src/sqlMapConfig.xml添加UserMapper.xml的映射
<mappers>
<mapper resource="com/itheima/dao/UserMapper.xml"/>
mappers>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rQlEHWnX-1597834865310)(/1578798536836.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YtdMexYY-1597834865312)(/1578798547894.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ATXV1x5I-1597834865313)(/1578798557237.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Bwortpmq-1597834865315)(/1578798567609.png)]
namespace: 包名.接口名
id: 方法名
resultType: 方法的返回值类型
select标签主体内容: 查询的SQL语句
编写MyBatis访问数据库的Java代码
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m1IPrMID-1597834865316)(1559463500041.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PACVMsmW-1597834865318)(1557809947051.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2fYQBGpX-1597834865320)(1557809924268.png)]
package com.itheima.test;
import com.itheima.dao.UserMapper;
import com.itheima.entity.User;
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 java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class TestUserMapper {
public static void main(String[] args) throws IOException {
// 1.得到核心配置文件的输入流
InputStream in = TestMybatis.class.getResourceAsStream("/sqlMapConfig.xml");
// 2.创建会话工厂建造类
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
// 3.创建会话工厂
SqlSessionFactory factory = builder.build(inputStream);
// 4.通过会话工厂得到会话对象
SqlSession session = factory.openSession();
// 5.由会话对象得到DAO接口的对象,由mybatis生成接口的代理对象。
UserMapper userMapper = session.getMapper(UserMapper.class);
// 6.实现CRUD
List<User> userList = userMapper.findAllUsers();
for (User user : userList) {
System.out.println(user);
}
// 7.释放资源
session.close();
}
}
注:UserMapper的对象是由MyBatis生成的接口代理对象
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oPDagwax-1597834865322)(1557809924268.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-W4PcS92x-1597834865324)(/1578799420110.png)]
注意:在核心配置文件中要记得配置接口映射文件的位置
测试类:
package com.itheima.test;
import com.itheima.dao.UserMapper;
import com.itheima.entity.User;
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.IOException;
import java.io.InputStream;
import java.util.List;
// MyBatis测试类
public class TestMyBatis {
// 测试方法
@Test
public void testMyBatis() throws IOException {
// 1.创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
// 2.得到会话工厂SqlSessionFactory类
// 类路径:加载文件返回流, /表示到了src
// InputStream in = TestMyBatis.class.getResourceAsStream("/sqlMapConfig.xml");
// Resources: 这个类是MyBatis提供的,就是加载src下的资源,不要写/开头
InputStream in = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = builder.build(in);
// 3.得到SqlSession对象, SqlSession相当于数据库的连接Connection
SqlSession sqlSession = sqlSessionFactory.openSession();
// 4.通过SqlSession对象得到Mapper接口的代理对象
// getMapper返回接口的实现类.(使用动态代理生成接口的实现类)
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
System.out.println("mapper = " + mapper);
// 5.Mapper接口的代理对象执行数据库的查询操作
List<User> users = mapper.findAllUsers();
User userById = mapper.findUserById(2);
// 6.关闭资源
sqlSession.close();
for (User user : users) {
System.out.println(user);
}
System.out.println("userById = " + userById);
}
}
根据用户 ID 查询用户
package com.itheima.entity;
import java.sql.Date;
/**
用户实体类对象 */
public class User {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
// 省略构造方法/getter/setter/toString
}
public interface UserMapper {
/*
通过id查询到一个用户
*/
User findUserById(Integer id);
}
在com.itheima.dao包下创建UserMapper.xml文件
<mapper namespace="com.itheima.dao.UserMapper">
<select id="findUserById" parameterType="java.lang.Integer" resultType="com.itheima.entity.User">
SELECT * FROM USER WHERE id=#{id};
select>
mapper>
在mapper中配置上面的UserMapper.xml文件
<mappers>
<mapper resource="com/itheima/dao/UserMapper.xml"/>
mappers>
public class TestUserMapper {
@Test
public void test01() throws IOException {
InputStream in = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory sessionFactory = builder.build(in);
SqlSession sqlSession = sessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User userById = mapper.findUserById(2);
System.out.println("userById = " + userById);
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h003Nlzo-1597834865325)(/1562579725880.png)]
MyBatis如何取到方法的参数放到sql中
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0Jfd0Vez-1597834865326)(/1578877776344.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vrSL4Zql-1597834865328)(/1578877785992.png)]
#{xx}: 先使用?占位, 后续将具体值赋值给?
通过id修改用户数据
/**
* 根据用户Id修改用户
*/
void updateUser(User user);
使用update标签:放置修改sql语句,根据用户id修改用户其它属性
<update id="updateUser" parameterType="com.itheima.entity.User">
UPDATE user set username=#{username}, birthday=#{birthday}, sex=#{sex}, address=#{address} where id=#{id};
update>
// 更新记录
@Test
public void testUpdateUser() {
User user = new User(6, "狐狸精",Date.valueOf("1996-05-10"),"女","狐狸洞");
userMapper.updateUser(user);
}
事务的处理:如果Java程序代码执行成功,但是数据库中并没有新增记录。原因是没有提交事务,在对数据库的更新操作中(增、删、改)要求提交事务。
sqlSession.commit(); // 方式一:手动提交事务
sqlSession = factory.openSession(true); // 方式二:自动提交
说明:如果在同一个方法中,有多个数据库操作,需要使用手动提交的方式。
如果SQL语句每条都是独立的,使用自动提交
如果是多条SQL语句组成一个功能,手动提交
参数是实体对象的时候,占位符#{}中的变量名是什么?
#{成员变量},使用?占位,取出参数对象中的成员变量值,赋值给?
开启事务有哪两种方式?
手动提交: sqlSession.commit();
自动提交:sqlSessionFactory.openSession(true);
根据id删除数据
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-assh5G7q-1597834865329)(1558087744181.png)]
/**
* 根据用户id删除用户
*/
void deleteUser(int id);
delete标签:放置删除sql语句,根据用户Id删除用户
<delete id="deleteUser" parameterType="int">
DELETE from user where id=#{id}
delete>
删除1号用户
// 删除记录
@Test
public void testDeleteUser() {
userMapper.deleteUser(11);
}
删除数据的步骤:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HZwxnhUT-1597834865331)(1558085199529.png)]
/**
* 新增用户
*/
void addUser(User user);
<insert id="addUser" parameterType="com.itheima.entity.User">
INSERT INTO user VALUES (null, #{username}, #{birthday},#{sex},#{address})
insert>
new User(null,"白龙马", Date.valueOf("2019-05-01"), "男", "东海龙宫");
编写SqlSession
复制入门案例模块,修改模块名为:mybatis_day01_02_framework,导入模块
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6nUHitWa-1597834865332)(/1562574976997.png)]
删除配置文件中的DTD约束,不然DOM解析会联网,会失败
com.itheima.mybatis
包com.itheima.mybatis
创建SqlSession类SqlSession
中编写getMapper
获取Mapper
的代理对象SqlSession sqlSession = new SqlSession();
UserMapper userMapper = session.getMapper(UserMapper.class);
import java.lang.reflect.Proxy;
// SqlSession的作用是获取Mapper的代理对象
public class SqlSession {
/*
Object newProxyInstance(ClassLoader loader, 类加载器
Class>[] interfaces, 接口
InvocationHandler h) 调用处理器
*/
public <T> T getMapper(Class<T> type) {
// 生成参数的代理对象
return (T)Proxy.newProxyInstance(
this.getClass().getClassLoader(),
new Class[] {type},
new MyInvocationHandler()
);
}
}
Mapper
的代理对象是用来执行SQL语句的
List<User> users = userMapper.findAllUsers();
我们先固定写一些数据
public class MyInvocationHandler implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 返回查询数据
ArrayList<User> list = new ArrayList<>();
list.add(new User(2, "张三", new Date(100), "男", "广州"));
list.add(new User(3, "李四", new Date(200), "女", "深圳"));
return list;
}
}
说出SqlSession的作用
SqlSession中有一个getMapper(接口.class),这个方法的作用就是生成接口的实现类
解析核心配置文件sqlMapConfig.xml,创建连接池
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tOy4qHXx-1597834865336)(1557836483705.png)]
package com.itheima.mybatis;
import com.alibaba.druid.pool.DruidDataSource;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import javax.sql.DataSource;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Configuration {
// 数据源
private DataSource dataSource;
public Configuration() {
// 加载sqlMapConfig.xml中的数据库链接参数
// 得到输入流
InputStream in = Configuration.class.getResourceAsStream("/sqlMapConfig.xml");
// DOM解析
// 得到文档对象
SAXReader saxReader = new SAXReader();
try {
Document document = saxReader.read(in);
// 加载数据库连接参数
// 获得数据库连接字符串:driver
Element driverElement = (Element) document.selectSingleNode("//property[@name='driver']");
driver = driverElement.attributeValue("value");
// 获得数据库连接字符串:url
Element urlElement = (Element) document.selectSingleNode("//property[@name='url']");
url = urlElement.attributeValue("value");
// 获得数据库连接字符串:username
Element usernameElement = (Element) document.selectSingleNode("//property[@name='username']");
username = usernameElement.attributeValue("value");
// 获得数据库连接字符串:password
Element passwordElement = (Element) document.selectSingleNode("//property[@name='username']");
password = passwordElement.attributeValue("value");
// 创建数据源
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName(driver);
ds.setUrl(url);
ds.setUsername(username);
ds.setPassword(password);
this.dataSource = ds;
// TODO:加载接口映射文件
} catch (DocumentException e) {
e.printStackTrace();
}
}
}
Configuration类做了什么事情?
编写Mapper类封装UserMapper.xml数据
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IQVNXBLH-1597834865337)(1557835980878.png)]
package com.itheima.mybatis;
/**
用来封装映射文件的实体类
一个Mapper对象代表一条要操作的查询语句对象
*/
public class Mapper {
private String resultType; // 封装的数据类型
private String sql; // 要执行的SQL语句
// 省略getter/setter
}
Mapper实体类中有哪几个属性?
2个属性
private String resultType; // 方法的返回值类型
private String sql; // 要执行的SQL语句
解析UserMapper.xml并且封装到Mapper类中
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sDlQxfXX-1597834865340)(1557838070863.png)]
读取mapper中的resource属性值
解析resource对应的XML文件,得到namespace,id,resultType,sql的值
封装成Mapper对象,保存到Map集合中
package com.itheima.mybatis;
import com.alibaba.druid.pool.DruidDataSource;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import javax.sql.DataSource;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Configuration {
// 数据源
private DataSource dataSource;
// 封装其它的映射文件中属性
private Map<String, Mapper> mappers = new HashMap<>();
public Configuration() {
// 加载sqlMapConfig.xml中的数据库链接参数
// 得到输入流
InputStream in = Configuration.class.getResourceAsStream("/sqlMapConfig.xml");
// DOM解析
// 得到文档对象
SAXReader saxReader = new SAXReader();
try {
Document document = saxReader.read(in);
// 加载数据库连接参数
// 获得数据库连接字符串:driver
Element driverElement = (Element) document.selectSingleNode("//property[@name='driver']");
driver = driverElement.attributeValue("value");
// 获得数据库连接字符串:url
Element urlElement = (Element) document.selectSingleNode("//property[@name='url']");
url = urlElement.attributeValue("value");
// 获得数据库连接字符串:username
Element usernameElement = (Element) document.selectSingleNode("//property[@name='username']");
username = usernameElement.attributeValue("value");
// 获得数据库连接字符串:password
Element passwordElement = (Element) document.selectSingleNode("//property[@name='username']");
password = passwordElement.attributeValue("value");
// 创建数据源
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName(driver);
ds.setUrl(url);
ds.setUsername(username);
ds.setPassword(password);
this.dataSource = ds;
// 加载接口映射文件
Element mapperElement = (Element) document.selectSingleNode("//mapper[@resource]");
// com/itheima/dao/UserMapper.xml
String resource = mapperElement.attributeValue("resource");
InputStream mapperIn = Configuration.class.getResourceAsStream("/" + resource);
// DOM解析
SAXReader reader = new SAXReader();
Document mapperDocument = reader.read(mapperIn);
// rootElement:
Element rootElement = mapperDocument.getRootElement();
String namespace = rootElement.attributeValue("namespace");
/* */
Element select = rootElement.element("select");
// 获得id属性值
String id = select.attributeValue("id");
// 获得返回值类型
String resultType = select.attributeValue("resultType");
// 获得标签体内容:sql语句字符串
String sql = select.getTextTrim();
// 创建Mapper对象
Mapper mapper = new Mapper(namespace, id, resultType, sql);
// 将Mapper对象添加到集合mappers中
mappers.put(namespace + "." + id, mapper);
} catch (DocumentException e) {
e.printStackTrace();
}
}
// 省略getter/setter
}
hashMap中键和值分别是什么?
键:
值:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OhZxwkC5-1597834865341)(/1562573317270.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-n6XYsqOU-1597834865343)(1557843552782.png)]
通过连接池得到连接对象
使用JDBC访问数据库执行SQL语句
处理结果集中的每条记录
使用反射将每条记录封装成一个对象
关闭资源
package com.itheima.mybatis;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
// Mapper的代理对象是用来执行SQL语句的
public class MyInvocationHandler implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 去数据库查询数据返回
String methodName = method.getName();
// 得到这个方法声明是的Class对象
String className = method.getDeclaringClass().getName();// 得到类全名
String allName = className + "." + methodName;
System.out.println("allName = " + allName);
// 通过键找到值,mapper对象
Configuration configuration = new Configuration();
Mapper mapper = configuration.getMappers().get(allName);
String sql = mapper.getSql();
String resultTypeString = mapper.getResultType(); // com.itheima.entity.User
Class<?> resultType = Class.forName(resultTypeString);
// 执行SQL
// 1.通过连接池得到连接对象
DruidDataSource dds = configuration.getDds();
Connection conn = dds.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql);
// 2.使用JDBC访问数据库执行SQL语句
ResultSet rs = pstmt.executeQuery();
// 3.处理结果集中的每条记录
ArrayList list = new ArrayList();
// 4.使用反射将每条记录封装成一个对象
while (rs.next()) {
// 1.创建对象
Object user = resultType.newInstance();
Field[] fields = resultType.getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
// 获取成员变量名
String name = field.getName();
// 获取字段值
Object value = rs.getObject(name);
field.set(user, value);
}
// 5.将对象添加到集合中
list.add(user);
}
// 6.关闭资源
rs.close();
pstmt.close();
conn.close();
return list;
}
}
结果是如何封装的?
使用反射对结果进行封装.为的是扩展性,兼容所有的类
将查询结果中的一条记录转成一个对象,使用反射给成员变量赋值
Debug自定义MyBatis流程
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I6LJInw9-1597834865345)(/1597826873718.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BGgqMXMG-1597834865346)(/1597826913770.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Z7V4tx7c-1597834865348)(/1597826946322.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3DKdLaPe-1597834865350)(/1597827010880.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xxzpudoy-1597834865352)(/1597827051086.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qANtNfpg-1597834865354)(/1597827127210.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Y5PO5B7G-1597834865357)(/1597827229086.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4chqEBOG-1597834865358)(/1597827274390.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WSH9WLfM-1597834865360)(/1597827330299.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eH9PuLz9-1597834865361)(/1597827385447.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rdyWQiiI-1597834865364)(/1597827499534.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CjhZyScZ-1597834865365)(/1597827543802.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZGOmcGhz-1597834865366)(/1597827655145.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0kwszXNg-1597834865368)(/1597827713217.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I0P5rmlE-1597834865369)(/1597828042025.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bKlnETlr-1597834865370)(/1597828064340.png)]
能够配置接口映射文件
<mapper namespace="com.itheima.dao.UserMapper">
<select id="findAllUsers" resultType="com.itheima.entity.User">
SELECT * FROM user;
select>
mapper>
namespace: 包名.接口名
id: 方法名
resultType: 方法的返回值类型
标签主体内容: 要执行的SQL语句
能够配置主配(核心)置文件
<configuration>
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/day17"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
dataSource>
environment>
environments>
<mappers>
<mapper resource="com/itheima/dao/UserMapper.xml"/>
mappers>
configuration>
driver: 驱动的包名.类名
url: 数据的URL
username: 账号
password: 密码
mapper标签的resource: 接口映射文件的路径, 路径是以/分割的
能够配置mybatis的环境
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Q7Yjz2BK-1597834865372)(/1578820054038.png)]
能够完成单表的CRUD操作