Mybatis框架的集成使用

1_框架概述

框架是一个半成品,已经对基础的代码进行了封装并提供相应的API,开发者在使用框架时直接调用封装好的api可以省去很多代码编写,从而提高工作效率和开发速度,框架是一种经过校验、具有一定功能的半成品软件.

经过校验:指框架本身经过测试,且框架自身所具有的功能已经实现具有一定功能:指框架可以完成特定的功能,不同的框架功能不同

半成品软件:指框架自身是一个软件,但是该软件无法直接运行,需要配合其他的程序才可以完成指定的工作.

框架的工作模式:

开发工程师建立在框架的基础之上完成开发部分功能 加 框架自身完成部分功能组成一个完整的产品

2_MyBatis 基础

2.1_MyBatis的概述

MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集MyBatis 可以使用简单的 XML 或注解来配置和映射原生类型、接口和 Java  POJOPlain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

mybatis框架架构图:

我们把Mybatis的功能架构分为三层:

  1. API接口层:提供给外部使用的接口API开发人员通过这些本地API来操纵数据库。接口层一接收到调用请求就会调用数据处理层来完成具体的数据处理。
  2. 数据处理层:负责具体的SQL查找、SQL解析、SQL执行和执行结果映射处理等。它主要的目的是根据调用的请求完成一次数据库操作。
  3. 基础支撑层:负责最基础的功能支撑,包括连接管理、事务管理、配置加载和缓存处理,这些都是共用的东西,将他们抽取出来作为最基础的组件。为上层的数据处理层提供最基础的支撑。

2.2_环境准备

需求: 向用户表中添加一条数据

  1. 添加项目需要的 jar
  2. lombok-1.16.6.jar(新的IDEA不用添加)

Lombok自动生成 getter/setter/toString 等方法使用的前提是已经在 idea 中安装了 lombok 插件

  1. mysql-connector-java-5.1.26-bin.jar

MySQL 数据库的 JDBC 驱动包,访问 MySQL 必须导入备 jar

  1. mybatis-3.4.5.jar MyBatis 框架的核心 jar
  2. 创建一张用户表:user

CREATE TABLE `user` (

`id` bigint(20) NOT NULL AUTO_INCREMENT,

`name` varchar(255) DEFAULT NULL,

`age` int(255) DEFAULT NULL,

`salary` decimal(10,0) DEFAULT NULL

PRIMARY KEY (`id`)

) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

  1. 根据表结构创建实体类

@Getter@Setter@ToString

@NoArgsConstructor@AllArgsConstructor

public class User {

private Long id;

private String name;

private Integer age;

private BigDecimal salary;

private Date hiredate;

}

  1. mybatis主配置文件: mybatis-config.xml
  2. 在项目的resources(source folder)下创建mybatis-config.xml配置文件
  3. 拷贝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">

添加环境配置(事务管理器 / 连接池 / 映射文件)

<?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="dev">

<environment id="dev">

<!--

MyBatis 内置的事务管理器

JDBC:org.apache.ibatis.transaction.jdbc.JdbcTransaction的别名

-->

<transactionManager type="JDBC"/>

<!--

MyBatis 内置的连接池

POOLED:org.apache.ibatis.datasource.pooled.PooledDataSource的别

-->

<dataSource type="POOLED">

<!--

driver:这是POOLED连接池对象的驱动类的属性名,

Druid连接池对象的驱动类属性名是driverClassName

-->

<property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql:///mybatis"/

<property name="username" value="root"/>

<property name="password" value="admin"/>

</dataSource>

</environment>

</environments>

<mappers>

<mapper resource="cn/UserMapper.xml"/> </mappers>

</configuration>

  1. mapper 映射文件: UserMapper.xml

mybatis,访问数据库的SQL语句是编写在mapper配置文件中的,程序员按照这个文件约定的格式进行配置即可

中创建配置文件: UserMapper.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">

在配置文件中添加 SQL 语句

<!--

一个项目可以操作多张表

每张表都需要一个mapper配置文件来编写SQL语句

每条SQL语句都需要有一个唯一的标识

这个唯一的标识由 namespace + sqlid 组成

使用下面的namespace+sqlid就得到了保存用户信息的唯一标识:

insert 接下来,我们就可以使用上面的标识找到这条SQL语句了

-->

<mapper namespace="cn.UserMapper"> <insert id="insert">

insert into user(name,age,salary,hiredate)

values(#{name}, #{age}, #{salary}, #{hiredate})

</insert>

</mapper>

注意: 一定记得在 mybatis-config.xml 配置文件中关联映射文件

<mappers>

<!--

这里是mapper文件的路径,所以使用/分割

-->

<mapper resource="cn/UserMapper.xml"/> </mappers>

2.3_DAO层开发

  1. dao接口

创建 dao 接口: IUserDAO.java

public interface IUserDAO {

/**

  • user表中插入一条数据
  • @param u 要插入的数据

 */

void insert(User u);

}

  1. dao 接口实现类

创建 dao 的实现类: UserDAOImpl.java

按以下 API 实现数据的保存操作:

  1. SqlSessionFactory : 对连接池(DataSource)的封装

SqlSession openSession() : 获取SqlSession对象

  1. SqlSession,对连接(Connection)的封装

int insert(String statementid, Object param);

statementid: mapper配置文件中的namespace+sqlid组成 void commit(): 提交事务

void close() : 释放资源

  1. 调用 SqlSession 中的 insert 方法,执行指定的 SQL

public class UserDAOImpl implements IUserDAO { public void insert(User u) {

try {

InputStream in = Resources.getResourceAsStream("mybatis-config.xml");

SqlSessionFactory fac = new

SqlSessionFactoryBuilder().build(in);

SqlSession session = fac.openSession();

session.insert("UserMapper.insert",

);

session.commit();

session.close();

} catch (Exception e) {

e.printStackTrace();

}

}

}

在测试类中测试 insert 方法

public class UserDAOTest {

private IUserDAO dao = new UserDAOImpl();

@Test

public void testInsert() {

User u = new User(null,"张三",20,new BigDecimal(20000), new Date()); dao.insert(u);

}

}

2.4_MyBatis 执行流程

  • 加载主配置文件(mybatis-config.xml)到内存中,将数据封装成对象Configuration/Environment/TransactionManager/DataSource
  • 通过操作拿到访问数据库的基本信息,根据这些数据创建 SqlSessionFactory 对象
  •  SqlSessionFactory 对象中获取到 SqlSession 对象,然后执行SQL
  • INSERT INTO user(name,age,salary,hiredate) VALUES(#{name},#{age},#{salary},#{hiredate})

被翻译成

INSERT INTO user(name,age,salary,hiredate)

VALUES(?, ?, ?, ?)

  1. 使用 PreparedStatement 来执行指定的SQL

从传递进来的 User 对象中依次获取到 name/age/salary/hiredate这些属性的值这里需要使用到内省机制来访问对象中的属性

:

在加载完当前映射文件之后,会将SQL中的 #{} OGNL表达式翻译成对应的占位符?,

执行上面的SQL,需要将数据设置给当前的语句对象 ps.setObect(1, 从参数中获取到name属性的值); ps.setObect(2, 从参数中获取到age属性的值); ps.setObect(3, 从参数中获取到salary属性的值); ps.setObect(4, 从参数中获取到hiredate属性的值);

操作步骤回顾:

  1. 创建项目,导入jar
  2. 创建表和模型

3 创建 mybatis-config.xml 配置环境

4 创建 UserMapper.xml 文件 存在 mapper包中,配置sql语句

5 创建 dao 接口和实现类

6 启动 MyBatis 去执行插入操作

  1. 测试插入操作

3_获取插入数据生成的主键

在开发中,如果需要获取到数据库中自动生成的主键,那么使用 MyBatis 应该如何实现呢?

<insert id="insert" useGeneratedKeys="true" keyProperty="id" keyColumn="id"> insert into user(name,age,salary,hiredate)

values(#{name}, #{age}, #{salary}, #{hiredate})

</insert>

useGeneratedKeys: 是否要获取自动生成的主键

keyColumn: 表中的主键列

keyProperties: 主键列对应的属性

表示从获取哪个列的值封装到哪个属性中

通过上面的配置,在执行了保存操作后,mybatis 会自动将主键值封装到传递进来的 User 对象的 id 属性

所以,此时的 User 对象的 id 属性就有值了(在保存之前是没有的)

parameterType : 参数类型,可以不用写,MyBatis自己通过用户传入的对象去推导.

4_更新和删除操作

和保存操作的开发流程一致,在完成了保存操作之后,更新和删除操作一样可以实现 dao 中更新的实现

@Overrid

public void update(User u) {

try {

InputStream in = Resources.getResourceAsStream("mybatis-config.xml");

SqlSessionFactory fac = new SqlSessionFactoryBuilder().build(in);

SqlSession session = fac.openSession();

session.update("UserMapper.update", u);

session.commit();

session.close();

} catch (Exception e) { e.printStackTrace();

}

}

更新在 mapper 中的 SQL

<update id="insert">

update user

set name=#{name}, age = #{age}, salary = #{salary}, hiredate = #{hiredate} where

id = #{id}

</insert>

dao 中删除的实现

@Override

public void delete(long id) {

try {

InputStream in = Resources.getResourceAsStream("mybatis-config.xml");

SqlSessionFactory fac = new SqlSessionFactoryBuilder().build(in);

SqlSession session = fac.openSession();

session.delete("UserMapper.delete", id);

session.commit();

session.close();

} catch (Exception e) { e.printStackTrace();

}

}

删除在 mapper 中的 SQL

<delete id="delete">

delete from user where id = #{id}

</delete>

注意:

1 当传入的只有一个普通类型(一个值)的时候#{} 中的名称可以随便写,但是建议见名知义

2 不管使用的是 insert 方法还是 delete 方法,底层调用的还是update方法,通过sql语句来区别dml操作

5_查询操作

根据 id 查询用户

dao 实现

@Override

public User selectOne(long id) {

User u = null;

try {

InputStream in = Resources.getResourceAsStream("mybatis-config.xml"); SqlSessionFactory fac = new SqlSessionFactoryBuilder().build(in); SqlSession session = fac.openSession();

u = session.selectOne("cn.UserMapper.selectOne",

id);

session.close();

} catch (Exception e) {

e.printStackTrace();

}

return u;

}

mapper 中的 SQL

<select id="selectOne" resultType="cn.domain.User"> select * from user where id = #{id}

</select>

 DML 不一样的地方,查询操作需要指定把查询的结果集数据封装成什么类型的对象,resultType 属性就是这个作用

思考: resultType 可以不配置吗? 不可以,需要告诉 MyBatis 把一行数据封装成什么类型的对象

目前: 需要模型的属性和表的列需要一一匹配,如果不匹配,无法获取到数据.

查询所有用户

dao 实现

@Override

public List<User> selectList() {

List<User> users = null;

try {

InputStream in = Resources.getResourceAsStream("mybatis-config.xml"); SqlSessionFactory fac = new SqlSessionFactoryBuilder().build(in); SqlSession session = fac.openSession(); users =

session.selectList("cn.UserMapper.selectAll");

session.close();

} catch (Exception e) { e.printStackTrace();

}

return users;

}

mapper 中的 SQL

<select id="selectAll" resultType="cn.domain.User"> select * from user

</select>

6_细节处理

类型别名

在查询操作中, 我们需要使用result属性指定数据封装的类型, 这里的值类型的全限定名, 每次都编写的话比较麻烦,为了简化这里的配置,我们可以在主配置文件(mybatis-config.xml)中对指定的类型做别名的配置

<!-- 为指定包中的类来生成别名,默认是类的简单名称 -->

<typeAliases>

<package name="cn.domain"/> </typeAliases>

如此,我们在查询的SQL, 使用类的全限定名和使用别名是等价的修改前:

<select id="selectAll" resultType="cn.User"> select * from user

</select>

修改后:

<select id="selectAll" resultType="User">

select * from user

</select>

日志管理

在持久层的开发过程中,我们程序员需要随时观察SQL的执行情况,如果sql有问题,我们能够及时发现所以,如果能够在控制台中将我们执行的SQL全部打印出来,那么就可以方便的观察SQL的相关问题

配置日志文件监控MyBatis的运行.

  1. 将日志相关的jar包添加到项目中

​​​​​​​

2. resources(source folder)中创建配置文件, log4j.properties ,添加下面的内容(直接拷贝)

  1. Global logging configuration log4j.rootLogger=ERROR, stdout
  2. 配置要打印日志的包 log4j.loggr..mybatis=TRACE
  3. Console output...

log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

将配置中的 包路径修改为项目中对应的路径,我们这里可以使用: cn.mybatis

到此,我们每执行一条 SQL, 都会在控制台中打印出来,这非常有助于我们对 SQL 的分析,特别是 SQL 不正确的时候

7_抽取 MyBatisUtil 工具类

 JDBC 中的连接池使用一样,在整个项目中,我们只需要一个SqlSessionFactory对象,而不需要每次都创建一个新的,

所以,我们将SqlSessionFactory的创建和SqlSession对象的获取都抽取到工具类中: MyBatisUtil

注意:

加载配置文件没有填写:

8_抽取db.properties

在主配置文件中配置的内容较多, 其中包括我们修改频率较高的数据库连接信息(driver/url/username/password),我们可以在修改这些信息的过程中误改或者误删到其他的配置,为了解决这个问题,我们仍然是将这些信息配置到db.propertie配置文件中,然后再合并到主配置文件即可,如下:

db.properties

driverClassName=com.mysql.jdbc.Driver

url=jdbc:mysql://localhost:3306/javaweb

username=root

password=admin

mybatis-cofnig.xml

<configuration>

<!-- 关联db.properties:为了把连接数据库的信息单独放到一个配置文件 --> <properties resource="db.properties" />

<!-- 为指定包中的类来生成别名 -->

<typeAliases>

<package name="cn.domain"/> </typeAliases>

<!-- 连接数据库的环境

default:指定使用哪一个环境的配置

-->

<environments default="dev">

<environment id="dev">

<transactionManager type="JDBC"/>

<dataSource type="POOLED">

<!--

使用${key}取出db.properties中配置的信息

keydb.properties文件中的可以一直即可

-->

<property name="driver" value="${driverClassName}"/> <property name="url" value="${url}"/>

<property name="username" value="${username}"/> <property name="password" value="${password}"/>

</dataSource>

</environment>

</environments>

<!-- 关联映射文件 -->

<mappers>

<mapper resource="cn\mapper\ProductMapper.xml"/> </mappers>

</configuration>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/40607.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【超万卡GPU集群关键技术深度分析 2024】

文末有福利&#xff01; 1. 集群高能效计算技术 随着大模型从千亿参数的自然语言模型向万亿参数的多模态模型升级演进&#xff0c;超万卡集群吸需全面提升底层计算能力。 具体而言&#xff0c;包括增强单芯片能力、提升超节点计算能力、基于 DPU (Data Processing Unit) 实现…

Mx Admin 基于react18的后台管理系统

前言 Mx Admin 基于React18 vite5 antd5的后台管理系统&#xff0c; 基于RBAC的权限控制系统&#xff0c;动态菜单和动态路由支持tab路由缓存嵌套菜单支持多种菜单布局模式亮暗色主题切换

Enzo Life Sciences热点分享:细胞治疗中的T细胞活化

细胞治疗&#xff08;Cell Therapy&#xff09;作为一种新近发展起来的癌症治疗方法&#xff0c;是一种利用患者自体&#xff08;或异体&#xff09;的成体细胞&#xff08;或干细胞&#xff09;对组织、器官进行修复的治疗方法。通常是由免疫细胞和相关的细胞产生调节细胞功能…

Java判断范围型的数据是否存在重叠(数值类型、日期类型)

为什么写这么一篇文章呢&#xff1f; 遇到了个问题&#xff0c;同一天可以输入多个时间段&#xff0c;但是每个时间段的时间不能出现重叠。 纳尼&#xff0c;这不就是判断数据返回是否有重叠的变种嘛~ 简单&#xff0c;开搞 数字范围是否重叠判断 这里以int类型为例了&…

【单片机毕业设计选题24046】-基于单片机的智能鱼缸设计

系统功能: 检测水温&#xff0c;水温过低开启PTC加热。检测水位&#xff0c;水位过低开启水泵抽水。检测湿度&#xff0c;湿度过高则开启风扇通风。 检测PH值和浑浊度&#xff0c;TTS语音播报功能&#xff0c;OLED显示系统信息&#xff0c;蓝牙模块连接手机APP。 系统上电后…

IT专业入门,高考假期预习指南—初识产品经理BRD、MRD 和 PRD

七月来临&#xff0c;各省高考分数已揭榜完成。而高考的完结并不意味着学习的结束&#xff0c;而是新旅程的开始。对于有志于踏入IT领域的高考少年们&#xff0c;这个假期是开启探索IT世界的绝佳时机。作为该领域的前行者和经验前辈&#xff0c;你是否愿意为准新生们提供一份全…

AI 芯片之战:开启智能新时代的关键角逐

在科技发展的浪潮中&#xff0c;一场围绕 AI 芯片的激烈竞争正在全球范围内如火如荼地展开。多家巨头纷纷投身其中&#xff0c;使得这场混战已然进入白热化阶段。 AI 芯片&#xff0c;作为推动人工智能发展的核心硬件&#xff0c;其作用举足轻重。它能够高效地处理海量的数据&a…

生物分子生物学实验过程的自动化与智能监控系统设计

开题报告&#xff1a;生物分子生物学实验过程的自动化与智能监控系统设计 一、引言 随着生物科学技术的飞速发展&#xff0c;生物分子生物学实验在科研、医疗、农业等领域的应用日益广泛。然而&#xff0c;传统的生物分子生物学实验过程大多依赖于人工操作&#xff0c;存在操…

java web 部分

jsp作用域由大到小 过滤器有哪些作用&#xff1f; 过滤器的用法&#xff1f;&#xff08;对客户端的请求统一编码和对客户端进行认证&#xff09; JSP和Servlet中的请求转发分别如何实现&#xff1f; JSP 和 Servlet 有哪些相同点和不同点&#xff0c;他们之间的联系是什么…

PCB设计时,信号走线要先过ESD/TVS管,这是为什么?

目录 为什么有上面这个问题&#xff1f; 问题的原因——走线电感 走线电感的阻抗 电感的影响 小结 都说接口处的信号要先过ESD/TVS管&#xff0c;然后拉到被保护器件&#xff0c;为什么不这样做效果就不好&#xff1f;那如果受板子实际情况限制&#xff0c;必须这样layout…

Zabbix 配置MySQL数据库监控

Zabbix MySQL数据库监控简介 通过 Zabbix 监控 MySQL 数据库&#xff0c;可以获取有关数据库性能、运行状况和资源使用情况的详细信息&#xff0c;帮助及时发现和解决问题。 Zabbix官方提供了一个名为MySQL by Zabbix agent的监控模板&#xff0c;该模板专为 Zabbix 通过 Zabb…

华为5288 V5服务器安装BCLinux8U4手记

本文记录了华为5288 V5服务器安装BCLinux8U4操作系统的过程。 一、系统环境 1、服务器 华为FusionServer Pro 5288 V5服务器 2、操作系统 BCLinux-R8-U4-Server-x86_64-220725.iso 官网下载地址 sha256sum&#xff1a;1d31d3b8e02279e89965bd3bea61f14c65b9d32ad2ab6d4eb…

DTP 抽取出错:data target is locked by process***

怎么会显示被几年前的一个process lock住了呢&#xff1f; 搞不明白。 不管怎样&#xff0c;去RSPM_MONITOR改&#xff0c;data target填上ADSO名&#xff0c;选时间&#xff0c;Process status选Y。 找到这条&#xff0c;双击&#xff0c;发现是active的状态。可能是因为前后…

springboot城市菜园共享系统-计算机毕业设计源码00524

目 录 摘要 1 绪论 1.1 研究背景与意义 1.2 国内外研究现状和发展趋势 1.3论文结构与章节安排 2 城市菜园共享系统系统分析 2.1 可行性分析 2.2 系统流程分析 2.2.1 数据增加流程 2.2.2 数据修改流程 2.2.3 数据删除流程 2.3 系统功能分析 2.3.1 功能性分析 2.3.…

C++那些事之小项目实战-进程间通信

小项目实战之进程间通信 进程间通信是一个非常重要的话题&#xff0c;特别是像一些大型项目都有它的影子&#xff0c;例如&#xff1a;PostgreSQL使用了管道完成copy的进程间通信&#xff0c;那么本节也将基于这个主题&#xff0c;使用C去搭建一个进程间通过管道通信的demo出来…

消除笔怎么用?教你消除笔的正确用法

消除笔&#xff0c;也称为橡皮擦工具或克隆笔工具&#xff0c;是图像处理软件中的一种常用工具。它的主要作用是通过取样图像中的某一部分&#xff0c;然后覆盖掉不想要的图像内容&#xff0c;从而实现修复、去除瑕疵等效果。那么有哪些软件具有消除笔功能&#xff0c;又是怎么…

网络安全入门教程(非常详细)从零基础入门到精通,看完这一篇就够了。

学前感言: 1.这是一条坚持的道路,三分钟的热情可以放弃往下看了.2.多练多想,不要离开了教程什么都不会了.最好看完教程自己独立完成技术方面的开发.3.有时多google,baidu,我们往往都遇不到好心的大神,谁会无聊天天给你做解答.4.遇到实在搞不懂的,可以先放放,以后再来解决. 基…

欧洲杯:高精度定位技术,重塑体育赛事新体验

随着科技的飞速发展&#xff0c;体育赛事的观赏体验与竞技水平正被不断推向新的高度。在即将到来的2024年欧洲杯赛场上&#xff0c;一项革命性的技术——高精度定位&#xff0c;正悄然改变着比赛的每一个细节&#xff0c;为球迷们带来前所未有的观赛享受&#xff0c;同时也为运…

昇思25天学习打卡营第7天|保存与加载

Python语言 AI框架&#xff1a;Mindspore 1.模型构建 class Network(nn.Cell):def __init__(self):super().__init__()self.flatten nn.Flatten()self.dense_relu_sequential nn.SequentialCell(nn.Dense(28*28, 512, weight_init"normal", bias_init"zeros…

力扣双指针算法题目:移动零

1.题目 . - 力扣&#xff08;LeetCode&#xff09; 2.思路解析 这个题目的思路和“使用递归排序快速排序解决数组的排序问题”相同 class solution { public:void QuickSort(vector<int>& nums, int left, int right){if (left > right) return;int key left…