发表于: 2020-10-07 23:29:56
1 1323
今天完成的事情:
遇到的问题:
MyBatis 概述(来源网址:https://blog.csdn.net/qq_42322548/article/details/92435625)
一、MyBatis介绍
MyBatis 原本是 apache 的一个开源项目 iBatis, 2010年这个项目由 apache software foundation 迁移到了 google code,并且改名为MyBatis。2013年11月迁移到 Github下(https://github.com/mybatis/mybatis-3/releases)。
MyBatis 是一个优秀的持久层框架,它对 JDBC 的操作数据库的过程进行封装,使开发者只需要关注 sql 本身,而不需要花费精力去处理例如注册驱动、创建 connection、创建 statement、手动设置参数、结果集检索等 JDBC 繁杂的过程代码。
Mybatis 通过 xml 或 注解 的方式将要执行的各种 statement(statement、preparedStatemnt、CallableStatement)配置起来,并通过 java 对象和 statement中 的 sql 进行映射生成最终执行的 sql 语句,最后由 MyBatis 框架执行 sql 并将结果集映射成 Java 对象并返回。
二、MyBatis 架构
1、MyBatis 配置文件。
SqlMapConfig.xml:此文件作为 MyBatis 的全局配置文件,配置了 MyBatis 的运行环境等信息。
mapper.xml:sql映射文件,配置了操作数据库的 sql 语句,此文件需要在 SqlMapConfig.xml 中加载。
2、通过 MyBatis 环境等配置信息构造 SqlSessionFactory(会话工厂)。
3、由会话工厂创建 SqlSession(会话),操作数据库需要通过 SqlSession 进行。
4、MyBatis 底层自定义了 Executor 执行器接口操作数据库,Executor 接口有两个实现,一个是基本执行器、一个是缓存执行器。
5、Mapped Statement 也是 MyBatis 一个底层封装对象,它包装了 MyBatis 配置信息及 sql 映射信息等,mapper.xml 文件中一个 sql 对应一个 Mapped Statement 对象,sql 的 id 即是 Mapped statement 的 id。
6、Mapped Statement 对 sql 执行输入参数进行定义,包括 HashMap、基本类型、pojo,Executor 通过 Mapped Statement 在执行 sql 前将输入的 Java 对象映射至 sql 中,输入参数映射就是 JDBC 编程中对 preparedStatement 设置参数。
7、Mapped Statement 对 sql 执行输出结果进行定义,包括 HashMap、基本类型、pojo,Executor 通过 Mapped Statement 在执行 sql 后将输出结果映射至 Java 对象中,输出结果映射过程相当于 JDBC 编程中对结果的解析处理过程。
三、MyBatis 运行过程
1、配置 MyBatis 的配置文件:mybatis-config.xml(名称不固定)。
2、通过配置文件,加载 MyBatis 运行环境,创建 SqlSessionFactory 会话工厂(SqlSessionFactory 在实际使用时按单例方式)。
3、通过 SqlSessionFactory 创建 SqlSession。SqlSession 是一个面向用户接口(提供操作数据库方法),实现对象是线程不安全的,建议 SqlSession 的应用场合在方法体内。
4、调用 SqlSession 的方法去操作数据。如果需要提交事务,需要执行SqlSession的commit()方法。
5、释放资源,关闭 SqlSession。
四、MyBatis 开发 DAO 的方法
使用 MyBatis 开发 Dao 通常有两个方法:原始 Dao 、Mapper 动态代理开发(官方推荐)。
1、原始 DAO
代码:https://blog.csdn.net/qq_42322548/article/details/91703546
需要程序员编写 DAO 接口及其实现类。
需要在 DAO 接口的实现类上注入 sqlSessionFactory,创建 sqlSessionFactory 时需要读取 mapper.xml 到内存。
通过创建 sqlSession 对象来调用 mapper 中的 sql 语句,在操作结束后需要手工进行提交,释放资源,返回结果。
存在的问题:
- Dao 实现类方法体中存在重复代码:通过 SqlSessionFactory 创建 SqlSession,调用 SqlSession 的数据库操作方法
- 调用 sqlSession 的数据库操作方法需要指定 statement 的 id,这里存在硬编码,不得于开发维护。
- 调用 sqlsession 方法时传入的变量,由于 sqlsession 方法使用泛型,即使变量类型传入错误,在编译阶段也不报错,不利于程序员开发。
2、Mapper 动态代理开发
代码:https://blog.csdn.net/qq_42322548/article/details/91718362
只需要程序员编写 mapper 接口(就是 dao 接口)。
程序员在编写mapper.xml(映射文件)和 mapper.java 需要遵循一个开发规范:
- mapper.xml中namespace就是mapper.java的类全路径。
- mapper.xml中statement的id和mapper.java中方法名一致。
- mapper.xml中statement的parameterType指定输入参数的类型和mapper.java的方法输入参数类型一致
- mapper.xml中statement的resultType指定输出结果的类型和mapper.java的方法返回值类型一致。
五、输入映射和输出映射
输入映射
parameterType:指定输入参数类型,可以为简单类型、pojo、hashmap。
MyBatis 通过 OGNL 从输入对象中获取参数值拼接在 sql 中。
对于综合查询,建议 parameterType 使用包装的 pojo,有利于系统扩展。
输出映射
MyBatis 将 sql 查询结果的一行记录数据映射为 pojo 对象(一对一),如果有多条数据则分别进行映射,并把对象放到容器 List 中(一对多)。
resultType:查询到的列名和映射的 pojo 的属性名一致时才能映射成功。
reusltMap:如果查询到的列名和映射的 pojo 的属性名不一致时,通过 resultMap 设置列名和属性名之间的映射关系,可以完成映射。
动态sql
if判断
where
foreach
sql片段
1.使用 Maven 搭建 Mybatis 环境(参考网址:https://blog.csdn.net/qq_42322548/article/details/89913220)
1.配置 maven 的 pom.xml 文件
报错
这些都通过百度解决了,但是查了好久,找不到关键字。
我在导入mysql驱动包的时候想到导入的驱动包需要和本地的MySQL版本一样吗?
于是在csdn发现了这个(https://blog.csdn.net/dylgs314118/article/details/102677942?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.channel_param)
看来有对应的关系的,我本地MySQL是5.7.31,导入的依赖包是5.1.31,刚好对应上了
2、参考的目录结构
3.创建实体类
实体类的属性需要与数据库表中的字段一一对应, 并有对应的 getter 和 setter。
学到这里发现对get,set方法,还有toString不是很熟悉需要去复习一下
4.添加 Mybatis 核心配置文件
在 resource 文件夹新建 mybatis-config.xml(名称不固定),该文件是 Mybatis 核心配置文件,配置文件内容为数据源、事务管理。
这里学会了创建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.properties 配置文件 -->
<properties resource="jdbc.properties"></properties>
<!-- typeAliases 设置类型别名 -->
<typeAliases>
<typeAlias alias="User" type="com.noteligible.pojo.User"/>
</typeAliases>
<!-- environments 环境配置 -->
<environments default="development">
<environment id="development">
<!-- 使用jdbc事务管理 -->
<transactionManager type="JDBC"></transactionManager>
<!-- 数据库连接池 -->
<!-- 数据库连接相关配置 ,这里动态获取jdbc.properties文件中的内容-->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!-- 加载 mapper 映射文件 -->
<mappers>
<mapper resource="com/noteligible/mapper/UserMapper.xml"/>
</mappers>
</configuration>
5、引用 jdbc.properties 文件,读取配置文件中的属性
在 resource 文件夹新建 jdbc.properties 配置文件,保存配置相关的信息。
JDBC 连接 MySQL5 使用驱动包 com.mysql.jdbc.Driver,JDBC 连接 MySQL6 及以上使用驱动包 com.mysql.cj.jdbc.Driver,且需要指定时区 serverTimezone。
# mysql驱动包名
jdbc.driver=com.mysql.jdbc.Driver
# 数据库连接地址
jdbc.url=jdbc:mysql:///db4
# 用户名
jdbc.username=root
# 密码
jdbc.password=wsj199599
前缀jdbc.需要对应上,不然就会报错
这些内容都没看见过,不懂意思
6.创建 sql 映射文件
在 mapper 文件夹新建 UserMapper.xml 文件,并在 Configuration.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:命名空间,用于隔离sql,实际开发中多用于 Mapper 代理中绑定接口 -->
<mapper namespace="test">
<!-- id:statement的id,或者叫做sql的id-->
<!-- parameterType:声明输入参数的类型 -->
<!-- resultType:声明输出结果的类型 -->
<!-- #{}:输入参数的占位符,相当于jdbc的占位符'?' -->
<select id="queryUserById" parameterType="int" resultType="User">
select * from user where id = #{id}
</select>
</mapper>
使用 resultType 时,其类属性名必须和查询的列名一致,如果不一致可以用 resultMap。
7.编写测试类
在 test 文件夹 新建 junit 测试类。
public class test {
private SqlSessionFactory sqlSessionFactory = null;
@Before
public void init() throws Exception{
// 1. 创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
// 2. 加载SqlMapConfig.xml配置文件
InputStream inputStream = Resources.getResourceAsStream("mybaits-config.xml");
// 3. 创建SqlSessionFactory对象
this.sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
}
@Test
public void testQueryUserById() {
// 4. 创建SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
// 5. 执行SqlSession对象执行查询,获取结果User
// 第一个参数是UserMapper.xml的statement的id,第二个参数是执行sql需要的参数;
User user = sqlSession.selectOne("queryUserById",1);
// 6. 打印结果
System.out.println(user);
// 7. 释放资源
sqlSession.close();
}
}
二.Mybatis 开发 DAO 之 Mapper 动态代理
前面导入依赖,配置jdbc文件,添加mybatis-config.xml步骤都一样。从创建sql映射文件开始不同
五、创建 sql 映射文件
在 mapper 文件夹新建 UserMapper.xml 文件,并在 Configuration.xml 文件中加载该文件。
编写 mapper.xml(映射文件)和 mapper.java 需要遵循一个开发规范:
- mapper.xml中namespace就是mapper.java的类全路径。
- mapper.xml中statement的id和mapper.java中方法名一致。
- mapper.xml中statement的parameterType指定输入参数的类型和mapper.java的方法输入参数类型一致
- mapper.xml中statement的resultType指定输出结果的类型和mapper.java的方法返回值类型一致。
<?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:命名空间,用于隔离sql,实际开发中多用于 Mapper 代理中绑定接口 -->
<mapper namespace="com.noteligible.mapper.UserMapper">
<!--增-->
<insert id="insertUser" parameterType="User">
insert into user values(#{id},#{username},#{PASSWORD})
</insert>
<!--删-->
<delete id="deleteUser" parameterType="User">
delete from user where id = #{id}
</delete>
<!--改-->
<update id="updateUser" parameterType="User">
update user set PASSWORD = #{PASSWORD},username = #{username} where id = #{id}
</update>
<!--通过id查找-->
<select id="queryUserById" parameterType="User" resultType="User">
select * from user where id = #{id};
</select>
<!-- 通过名字模糊查找-->
<select id="queryUserByName" parameterType="String" resultType="User">
select * from user where username like "%"#{value}"%"
</select>
</mapper>
六、创建 UserMapper 接口
在 mapper 文件夹新建 UserMapper 接口,并将 sql 映射文件中的 namespace 改成 UserMapper 接口的地址。
package com.noteligible.mapper;
import com.noteligible.pojo.User;
import java.util.List;
public interface UserMapper {
/**
* 增
* @param user
*/
void insertUser(User user);
/**
* 删
* @param user
*/
void deleteUser(int user);
/**
* 改
* @param user
*/
void updateUser(User user);
/**
* 通过id查找
* @param user
* @return
*/
User queryUserById(User user);
/**
* 通过名字模糊查找
* @param name
* @return
*/
List<User> queryUserByName(String name);
}
七、编写测试类
在 test 文件夹 新建 junit 测试类。
import com.noteligible.mapper.UserMapper;
import com.noteligible.pojo.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.Before;
import org.junit.Test;
import java.io.InputStream;
import java.util.List;
public class JunitTest {
private SqlSessionFactory sqlSessionFactory = null;
@Before
public void init() throws Exception{
// 1. 创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
// 2. 加载Mybatis-config.xml配置文件
InputStream inputStream = Resources.getResourceAsStream("Mybatis-config.xml");
// 3. 创建SqlSessionFactory对象
this.sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
}
//增加
@Test
public void testInsert(){
//获取sqlSession,和spring整合后由spring管理
SqlSession sqlSession = this.sqlSessionFactory.openSession();
//从sqlSession中获取Mapper接口的代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//建对象
User user = new User(3,"wangwu","456");
//调用对象
userMapper.insertUser(user);
sqlSession.commit();
sqlSession.close();
}
//删除
@Test
public void testDelete(){
//获取sqlSession,和spring整合后由spring管理
SqlSession sqlSession = this.sqlSessionFactory.openSession();
//从sqlSession中获取Mapper接口的代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//建对象
userMapper.deleteUser(1);
//调用对象
sqlSession.commit();
sqlSession.close();
}
@Test
public void updateUser(){
//获取sqlSession,和spring整合后由spring管理
SqlSession sqlSession = this.sqlSessionFactory.openSession();
//从sqlSession中获取Mapper接口的代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = new User(1,"zhangsan","123");
//调用对象
userMapper.insertUser(user);
sqlSession.commit();
sqlSession.close();
}
//通过id查找
@Test
public void testQueryUserById(){
//获取sqlSession,和spring整合后由spring管理
SqlSession sqlSession = this.sqlSessionFactory.openSession();
//从sqlSession中获取Mapper接口的代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//建对象
User user = new User();
//调用对象
user.setId(1);
User userResult = userMapper.queryUserById(user);
System.out.println(userResult);
}
//通过名字模糊查找
@Test
public void testQueryUserByName() {
//获取sqlSession,和spring整合后由spring管理
SqlSession sqlSession = this.sqlSessionFactory.openSession();
//从sqlSession中获取Mapper接口的代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//建对象
List<User> userList = userMapper.queryUserByName("wu");
System.out.println(userList);
}
}
在这里发现,虽然懂构造器的概率,理性上有认识,但在操作层面,或者感性,还是不熟悉用法,出现的错误很明显。还是需要多敲代码。
增
删
改
查(根据id)
查(根据名字模糊查找)
明天计划的事情:
把JDBC重写一遍,弄到各个代码间的相互作用,注意是如何运行的。
知道DAO层是什么,然后来编写DAO
收获:发现还有很多知识不熟练,比如构造器。只有理性的认识,实际操作起来就不太会了。还是多敲代码,碰到问题如何去解决,知道不懂知识点就再去复习一遍。
评论