Mybatis学习笔记 (一)
Mybatis学习笔记 (一)
第一部分 框架概述
1.1 什么是框架
1.1.1 什么是框架
框架(Framework)是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方法;
另一种定义认为,框架是可被应用开发者定制的应用骨架。前者是从应用方面而后者是从目的方面给出的定义。
简而言之,框架其实就是某种应用的半成品,就是一组组件,供你选用完成你自己的系统。简单说就是使用别人搭好的舞台,你来做表演。而且,框架一般是成熟的,不断升级的软件。
1.1.2 框架要解决的问题
框架要解决的最重要的一个问题是技术整合的问题,在J2EE的框架中,有着各种各样的技术,不同的软件企业需要从J2EE中选择不同的技术,这就使得软件企业最终的应用依赖于这些技术,技术自身的复杂性和技术的风险性将会直接对应用造成冲击。
而应用是软件企业的核心,是竞争力的关键所在,因此应该将应用自身的设计和具体的实现技术解耦。这样,软件企业的研发将集中在应用的设计上,而不是具体的技术实现,技术实现是应用的底层支撑,它不应该直接对应用产生影响。
框架一般处在低层应用平台(如 J2EE)和高层业务逻辑之间的中间层。
三层架构:
- 表现层:展示数据
- 业务层:处理业务需求
- 持久层:数据库交互
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NVYQLa4t-1585230875046)(https://i.loli.net/2020/03/26/mXUteku2oGFW5NL.png)]
1.1.3 软件开发的分层重要性
框架的重要性在于它实现了部分功能,并且能够很好的将低层应用平台和高层业务逻辑进行了缓和。为了实现软件工程中的“高内聚、低耦合”。把问题划分开来各个解决,易于控制,易于延展,易于分配资源。我们常见的MVC软件设计思想就是很好的分层思想。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ReLGonfu-1585230875049)(https://i.loli.net/2020/03/26/GqCRAzISXOn35kW.png)]
1.1.4 分层开发下的常见框架
持久层技术解决方案
- JDBC技术:Connection、PreparedStatement、ResultSet
- JdbcTemplate:spring中对jdbc的简单封装
- DBUtils:Apache
以上这些都不是框架,JDBC是规范,JdbcTemplate和DBUtils都只是工具类
常见的 JavaEE 开发框架
MyBatis
:解决数据的持久化问题的框架- 作为持久层的框架,还有一个封装程度更高的框架就是Hibernate,但这个框架因为各种原因目前在国内的流行程度下降太多,现在公司开发也越来越少使用。目前使用SpringData来实现数据持久化也是一种趋势。
Spring MVC
:解决 WEB 层问题的 MVC 框架Spring
:解决 WEB 层问题的 MVC 框架
1.1.5 MyBatis 框架概述
mybatis是一个优秀的基于java的持久层框架,它内部封装了jdbc,使开发者只需要关注sql语句本身,而不需要花费精力去处理加载驱动、创建连接、创建statement等繁杂的过程。
mybatis通过xml或注解的方式将要执行的各种statement配置起来,并通过java对象和statement中sql的动态参数进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射为java对象并返回。
采用ORM思想解决了实体和数据库映射的问题,对jdbc进行了封装,屏蔽了jdbcapi底层访问细节,使我们不用与jdbc api打交道,就可以完成对数据库的持久化操作。
ORM:Object Relational Mappging 对象关系映射,将数据库表和实体类以及实体类的属性对应起来,让我们可以操作实体类就失效操作数据库表
1.2 JDBC编程的分析
1.2.1 jdbc程序的回顾
public static void main(String[] args) { Connection connection = null; PreparedStatement preparedStatement = null; ResultSet resultSet = null; try { //加载数据库驱动 Class.forName("com.mysql.jdbc.Driver"); //通过驱动管理类获取数据库链接 connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis? characterEncoding=utf-8","root", "root"); //定义 sql 语句 ?表示占位符 String sql = "select * from user where username = ?"; //获取预处理 statement preparedStatement = connection.prepareStatement(sql); //设置参数,第一个参数为 sql 语句中参数的序号(从 1 开始),第二个参数为设置的参数值 preparedStatement.setString(1, "王五"); //向数据库发出 sql 执行查询,查询出结果集 resultSet = preparedStatement.executeQuery(); //遍历查询结果集 while(resultSet.next()){ System.out.println(resultSet.getString("id")+" "+resultSet.getString("username")); } } catch (Exception e) { e.printStackTrace(); }finally{ //释放资源 if(resultSet!=null){ try { resultSet.close(); } catch (SQLException e) { e.printStackTrace(); } } if(preparedStatement!=null){ try { preparedStatement.close(); } catch (SQLException e) { e.printStackTrace(); } } if(connection!=null){ try { connection.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
上边使用 jdbc 的原始方法(未经封装)实现了查询数据库表记录的操作。
1.2.2 jdbc 问题分析
- 数据库链接创建、释放频繁造成系统资源浪费从而影响统性能,如果使用数据库链接池可解决此问题。
- Sql 语句在代码中硬编码,造成代码不易维护,实际应用 sql 变化的可能较大, sql 变动需要改变 java代码。
- 使用 preparedStatement 向占有位符号传参数存在硬编码,因为 sql 语句的 where 条件不一定,可能多也可能少,修改 sql 还要修改代码,系统不易维护。
- 对结果集解析存在硬编码(查询列名), sql 变化导致解析代码变化,系统不易维护,如果能将数据库记录封装成 pojo 对象解析比较方便。
第二部分 Mybatis 框架快速入门
2.1 Mybatis 框架开发的准备
2.1.1 官网下载Mybatis框架
下载略
maven坐标配置如下:
<dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.5</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.6</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.12</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.10</version> <scope>test</scope> </dependency>
2.2 搭建 Mybatis 开发环境
2.2.1 创建 maven 工程
略
2.2.2 添加Mybatis坐标
见上面
2.2.3 编写实体类和dao接口
public class User implements Serializable { private Integer id; private String username; private Date birthday; private String sex; private String address; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", birthday=" + birthday + ", sex='" + sex + '\'' + ", address='" + address + '\'' + '}'; } }
IUserDao 接口就是持久层接口(也可以写成 UserDao 或者 UserMapper) ,具体代码如下:
//持久层接口 public interface IUserDao { List<User> findAll(); }
2.2.4 创建Mybatis的主配置文件lSqlMapConfig.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> <!-- 配置环境--> <environments default="mysql"> <!--配置mysql的环境 --> <environment id="mysql"> <!--配置事务类型--> <transactionManager type="JDBC"></transactionManager> <!-- 配置数据源(连接池) --> <dataSource type="POOLED"> <!-- 配置连接数据库的4个基本信息 --> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatisdb?useUnicode=true&characterEncoding=UTF8&useSSL=false&serverTimezone = GMT"/> <property name="username" value="root"/> <property name="password" value="1234"/> </dataSource> </environment> </environments> <!-- 告知 mybatis 映射配置的位置 --> <mappers> <mapper resource="***/***/IUserDao.xml"/> </mappers> </configuration>
2.2.5 编写持久层接口的映射文件 IUserDao.xml
创建位置: 必须和持久层接口在相同的包中。
名称: 必须以持久层接口名称命名文件名,扩展名是.xml
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jBliUcFS-1585230875053)(https://i.loli.net/2020/03/26/urILe9CPRGkNfbn.png)]
<?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"> <mapper namespace="***.***.IUserDao"> <!--配置查询所有,select id值为方法名 resultType不能漏掉--> <select id="findAll" resultType="com.itheima.domain.User"> select * from user ; </select> </mapper>
2.2.7 编写测试类
在resource根目录下创建一个与SqlMapConfig同级的log4j.properties
文件
# Set root category priority to INFO and its only appender to CONSOLE. #log4j.rootCategory=INFO, CONSOLE debug info warn error fatal log4j.rootCategory=debug, CONSOLE, LOGFILE # Set the enterprise logger category to FATAL and its only appender to CONSOLE. log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE # CONSOLE is set to be a ConsoleAppender using a PatternLayout. log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n # LOGFILE is set to be a File appender using a PatternLayout. log4j.appender.LOGFILE=org.apache.log4j.FileAppender log4j.appender.LOGFILE.File=d:\axis.log log4j.appender.LOGFILE.Append=true log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout log4j.appender.LOGFILE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n
在test/java中创建测试类
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(); } }
运行结果如下:
2.2.8 搭建环境的注意事项
-
创建 IUserDac.xml和 IUserDao.java时名称是为了和我们之前的知识保持一致。在 Mybatis中它把持久层的操作接口名称和映射文件也叫做: Mapper。所以: IUserDao和 IUserMapper是一样的。
-
在idea中创建目录的时候,它和包是不一样的。包在创建时
xx.xx.dao
它是三级结构,目录在创建时xx.xx.dao
是一级目录 -
mvbatis的映射配置文件位置必须和dao接口的包结构相同
-
映射配置文件的
mapper
标签namespace
属性的取值必须是dao接口的全限定类名 -
映射配置文件的操作配置(select等),
id
属性的取值必须是dao接口的方法名 -
此时不用再写dao的实现类
2.3 基于注解的mybatis入门
原先的xml配置步骤如下
第一步:读取配置文件
第二步:创建 SqlSessionFactory工厂
第三步:创建Sq1 Session
第四步:创建Dao接口的代理对象
第五步:执行dao中的方法
第六步:释放资源
有点麻烦
则可以更换为注解方式:此时也不需要编写持久层接口的映射文件 IUserDao.xml
2.3.1 配置文件中添加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> <!-- 配置环境--> <environments default="mysql"> <!--配置mysql的环境 --> <environment id="mysql"> <!--配置事物类型--> <transactionManager type="JDBC"></transactionManager> <!-- 配置数据源(连接池) --> <dataSource type="POOLED"> <!-- 配置连接数据库的4个基本信息 --> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatisdb?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone = GMT"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments> <!--注解--> <mappers> <mapper class="com.itheima.dao.IUserDao"/> </mappers> </configuration>
此时和使用xml配置相比,mapper
标签内容更换为指定dao接口的全限定类名
2.3.1 在dao接口添加注解
public interface IUserDao { @Select("select * from user") List<User> findAll(); }
注意:注解写在接口里面
在实际开发中,都是越简便越好,所以都是采用不写dao实现类的方式
不管使用XM还是注解配置
但是 Mybatis是支持写dao实现类的
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗