普通类创建获取session 方式_猿蜕变11——一文搞懂mybatis花式使用方式

看过之前的蜕变系列文章,相信你对mybatis有了初步的认识。但是这些还不够,我们今天进一步来了解下mybatis的一些用法。

猿蜕变同样是一个原创系列文章,帮助你从一个普通的小白,开始掌握一些行业内通用的框架技术知识以及锻炼你对系统设计能力的提升,完成属于你的蜕变,更多精彩内容,还是私信我吧,黑机构太多,老是举报我,大号都被封号了(由此可见对这些黑机构的伤害有多深)。

f4ec5749884195810db35e0e9699550f.png

86b8d90524ed88a9f7fac0d10f4254ae.png

d85f5231a060af992b705ed1b45bfadc.png

8a824a052f8f007d56e4658c795d025b.png

baa867476737b7f8670970ae383d4178.png

0bf857900267e446823e297615cfd1d4.png

我们第一个程序存在很多问题,每一次操作,都需要读取配置文件、初始化mybati框架。这样搞出来的程序上就一个字——渣!这让我想起了多年以前,某个小伙伴告诉我spring的正确使用一样,每次方法都让spring框架重新初始化了一次。哈哈,知道你也在看的,又是一波回忆杀。

在第一个mybatis程序中,获取SqlSession对象的方式也比较复杂,获取SqlSession对象的操作比较复杂,由于SqlSessionFactory本身就是用来管理SqlSession对象的,应用中一般情况下有一个就足够了!我们做一个小优化——使用单利模式来封装下,让一个SqlSessionFactory对象去管理SqlSession对象。

f9c665f9db68d42b89548df572342ee6.png

1.创建一个MyBatisUtil工具类:

package com.pz.route.util;import java.io.IOException;
import java.io.InputStream;import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;public class MyBatisUtil {private static SqlSessionFactory sqlSessionFactory;static{//读取主配置文件InputStream input = null;if (sqlSessionFactory == null) {try {input = Resources.getResourceAsStream("mybatis.xml");} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}synchronized (MyBatisUtil.class) {if (sqlSessionFactory == null){sqlSessionFactory = new SqlSessionFactoryBuilder().build(input);}}}}publicstatic SqlSession getSqlSession() {returnsqlSessionFactory.openSession();}}

上面的例子使用了静态代码块的方式创建了一个SqlSessionFactory对象,将SqlSession交给SqlSessionFactory进行管理。

2.修改TravelRouteDaoImpl类:

package com.pz.route.dao.impl;import org.apache.ibatis.session.SqlSession;import com.pz.route.dao.TravelRouteDao;
import com.pz.route.domain.TravelRoute;
import com.pz.route.util.MyBatisUtil;public class TravelRouteDaoImpl implements TravelRouteDao {private SqlSession sqlSession;@Overridepublic void add(TravelRoute travelRoute) {try {sqlSession = MyBatisUtil.getSqlSession();//新增数据操作sqlSession.insert("com.pz.route.dao.TravelRouteDao.add", travelRoute);//提交SqlSessionsqlSession.commit();//无需再做关闭,SqlSessionFactory会自动关闭sqlSession} catch (Exception e) {e.printStackTrace();}}}

SqlSession继承了AutoCloseable接口,SqlSessionFactory会自动关闭SqlSession。

48c0662a72546ba8aa8394603122daba.png

数据库的一些信息最好不要写死在xml里,大家基本上都是通过配置的方式读取数据库相关信息。在resources目录下创建db.properties配置文件,里面填写下面内容:

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/route?characterEncoding=utf8
jdbc.username=root
jdbc.password=123456

修改mybatis.xml文件,使用将数据库连接信息修改为使用配置文件的方式:

<?xml version="1.0"encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><!-- 引入数据库配置信息 --><properties resource="db.properties"/><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver"value="${jdbc.driverClassName}"/><property name="url"value="${jdbc.url}"/><property name="username"value="${jdbc.username}"/><property name="password"value="${jdbc.password}"/></dataSource></environment></environments><mappers><!--注册映射文件--><mapper resource="mapper/TravelRouteMapper.xml"/></mappers>
</configuration>

9188f15f951d79064acd93deabfd01f2.png

我们新建了Mybatis.xml作为使用Mytatis的主配置文件,那么这个主配置文件应该干些什么事情呢?

1.配置外部配置文件,方便程序使用(比如配置db.properties)

2.设置全局Domain类JavaBean的别名(每次使用类的名称空间写起来太麻烦了)

3.配置运行环境

4.配置mapper文件(有哪些数据操作使用了mybatis需要要告诉框架)

5. 设置全局的数据库操作配置,比如事务超时时间等等信息


我们看看mybatis.xml中的内容:

<properties resource="db.properties"/

这样配置以后,mybatis就可以从db.properties中获取数据库信息了。

我们看看这个配置我们在mapper文件中的写法:

<insert id="add"parameterType="com.pz.route.domain.TravelRoute">

在mapper中的parameterType需要使用类的名称空间:包名+类名的方式。每次这样写比较麻烦,也比较容易写错。MyBatis提供了<typeAliases>标签用以定义别名。

     <typeAliases><typeAlias type="com.pz.route.domain.TravelRoute"alias="TravelRoute"/></typeAliases>

这样子,在mapper中就可以直接使用TravelRoute来代替之前的 com.pz.route.domain.TravelRoute。

一个项目上线,需要经历多个阶段,一般来讲一个项目需要经过开发,测试,上线的生命周期。那么不可避免的,一个项目会有多个运行环境。

比如在开发阶段,应用往往运行在本地,测试阶段,会运行在测试服务器,到了应用上线之后,应用自然运行在生产机器上。在不同的环境下,数据库也会有多个,比如开发环境在A库,测试时在B库,项目上线以后在生产库C,那么为了支持不同的环境,mybatis提供了<environments>标签来支持多个环境的问题。

<environments default="development"><environment id="development"><transactionManager type="JDBC" /><dataSource type="POOLED"><property name="driver"value="${jdbc.driverClassName}" /><property name="url"value="${jdbc.url}" /><property name="username"value="${jdbc.username}" /><property name="password"value="${jdbc.password}" /></dataSource></environment><!--测试环境 --><environment id="test"><transactionManager type="JDBC" /><dataSource type="POOLED"><property name="driver"value="${jdbc.test.driver}" /><property name="url"value="${jdbc.test.url}" /><property name="username"value="${jdbc.test.user}" /><property name="password"value="${jdbc.test.password}" /></dataSource></environment></environments>

大家可以看到再environments标签中有两个environment子标签,配置了两个数据库信息environments标签中的default属性,用于选择到底使用的是哪个环境。

transactionManager标签用于设置事务管理器用于MyBatis的事务管理。MyBatis 支持两种事务管理器类型:

JDBC
需要再程序中使用通过SqlSession对象的commit()方法提交,通过rollback()方法回滚,默认情况下是需要手动提交的。

MANAGED
由Mybatis来管理事务的整个事务的生命周期,默认情况下,每次操作都会关闭数据库连接。

dataSource标签主要用于配置应用的数据源连接方式和数据库连接信息,使用type属性来设置数据源类型:

UNPOOLED
表示不使用数据库连接池,每次数据库操作Mybatis都需要创建一个Connection对象。

POOLED
使用Mybatis提供的数据库连接池。

JNDI
使用JNDI数据源(JNDI的方式一般是配置在应用服务器中)

1971993f76783fa0f93018584a910509.png

Mapper标签的作用就是通知Mybatis使用哪些mapper文件,一共有四种写法:

第一种:使用mapper文件的相对路径,这个路径是相对于classpath而言的。

<!--注册映射文件 --><mapper resource="mapper/TravelRouteMapper.xml" />

第二种:使用url

<!--注册映射文件 --><mapper url="D://xxx/xxxMapper.xml" />

第三种:使用类的名称空间,使用这种方式,需要满足以下几个规约:

1.Mapper文件名要与 Dao 接口名相同

2.Mapper文件要与接口在同一包中

3.Mapper文件中的 namespace 属性值为 Dao 接口的类的名称空间

<!--注册映射文件 --><mapper class="com.pz.route.dao.TravelRouteDao" />

第四种:使用mybatis提供的动态代理实现(无需自己实现xxxDaoImpl)

使用这种方式,需要满足以下几个规约:

(1)dao 使用 mapper 的动态代理实现(后面再将)

(2)Mapper文件名与 Dao 接口名相同

(3)Mapper文件与接口放在同一包中

(4)Mapper文件中的 namespace 属性值为 Dao接口的类的名称空间

<!--注册映射文件 -->
<mapper package="com.pz.route.dao" />

d7684cbfd12d6e6efc7c279c07a743c4.png

我们编写的第一个MyBatis程序,实现了一个向route数据库travel_route表中新增一条数据的功能,有一些比较值得注意的地方大家一起来看下:

<insert id="add"parameterType="com.pz.route.domain.TravelRoute">INSERTINTO travel_route(travel_route_name,travel_route_price,travel_route_introduce,travel_route_flag,travel_route_date,isThemeTour,travel_route_count,travel_route_cid,travel_route_image,travel_route_seller_id)values(#{travelRouteName},#{travelRoutePrice},#{travelRouteIntroduce},#{travelRouteFlag},#{travelRouteDate},#{isThemeTour},#{travelRouteCount},#{travelRouteCid},#{travelRouteImage},#{travelRouteSellerId})</insert>

id:需要执行的SQL语句的唯一标识,实际上它mybatix被识别的方式是namespace+id,一个id可被用代表一段需要执行的sql语句,在一个mapper文件中对id值的要求是不能重复出现的。

parameterType:sql语句中参数的类型,实际上MyBatis利用反射机制感知dao接口的参数类型,不写这个配置也是可以的

#{ }:这个符号表示参数,支持el表达式,我们通过JavaBean的方式做参数传递,花括号里的值为JavaBean的属性,如果属性也是对象,支持对象名.方法名的形式。

Mybatis事务提交,我们看TravelRouteDaoImpl:

try {sqlSession = MyBatisUtil.getSqlSession();//新增数据操作sqlSession.insert("com.pz.route.dao.TravelRouteDao.add", travelRoute);//提交SqlSessionsqlSession.commit();//无需再做关闭,SqlSessionFactory会自动关闭sqlSession} catch (Exception e) {e.printStackTrace();}

默认情况下Mybatis的事务是不会自动提交的,如果想自动提交事务,可以在MyBatisUtil中修改openSession的方法,传入参数true。如果不传入任何参数或者传入false,mybatis无法自动提交事务。

 public static SqlSession getSqlSession() {return sqlSessionFactory.openSession(true);}

如果不提交事务,数据是不会持久化到数据库的。

travel_route表,我们设置的主键是自增长类型,所以在编写SQL的时候,我们不用写入主键travel_route_id,如果我们想在插入数据后获取主键我们可以使用下面的方式:

  <selectKey resultType="Long"keyProperty="travelRouteId" order="AFTER">SELECT @@identity</selectKey>

这样子在mybatis完成insert操作之后后,会将当前写入数据的ID查询出来,重写Travle的toString方法,再编写一段程序看下效果:

       @Testpublic void testAddTravelRoute(){TravelRouteDao travelRouteDao = new TravelRouteDaoImpl();TravelRoute travelRoute = new TravelRoute();travelRoute.setTravelRouteName("新增线路2");travelRoute.setTravelRoutePrice(999d);travelRoute.setTravelRouteDate("2019-10-26");travelRoute.setTravelRouteFlag(1);travelRoute.setIsThemeTour("1");travelRoute.setTravelRouteCount(0);travelRoute.setTravelRouteCid(1);travelRoute.setTravelRouteIntroduce("双导游服务,免收服务小费,周全照顾贴心服务随心出游!品尝越南特色国宝美食,升级一餐越式炸鸡火锅宴!");travelRoute.setTravelRouteImage("img/product/small/m3db4d2277b5df3d98597f79082ef92d6d.jpg");travelRoute.setTravelRouteSellerId(1L);System.out.println("before insert===");System.out.println(travelRoute);travelRouteDao.add(travelRoute);System.out.println("after insert===");System.out.println(travelRoute);}

我们再在TravelRouteDaoImpl中commit打印增加两行打印代码

@Overridepublic void add(TravelRoute travelRoute) {try {sqlSession = MyBatisUtil.getSqlSession();//新增数据操作sqlSession.insert("com.pz.route.dao.TravelRouteDao.add", travelRoute);System.out.println("before commit===");System.out.println(travelRoute);//提交SqlSessionsqlSession.commit();//无需再做关闭,SqlSessionFactory会自动关闭sqlSession} catch (Exception e) {e.printStackTrace();}}

运行程序后,我们可以清晰地看到,在commit之前,id已经有值了,实际上,当insert语句执行后,commit之前,主键id已经返回了数据,这个事务不管是commit或者是rollback,travel_route的主键已经使用掉一个了,再做insert操作mysql只会分配一个新的主键。由此我们得出一个结论:数据库主键的分配和是否提交无关,只要执行了insert操作,mysql就会分配一个主键。

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

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

相关文章

Ubuntu配置IPFS的环境

参考链接 Ubuntu上IPFS环境搭建 - 简书 下载安装包 下载地址&#xff1a;https://dist.ipfs.io/#go-ipfs页面会自动根据你的操作系统提供适合的下载安装包&#xff0c;所以需要在Ubuntu环境下点开上面那个链接&#xff0c;网页自动识别当前的平台并提供对应的版本&#xff0c…

composer升级_Composer-命令简介

简介Composer 是一个用于 PHP 依赖管理的工具。它实现了让你声明项目所依赖的库&#xff0c;并帮你完成安装/更新过程。以下命令来自 composer version 1.8.0。翻译使用【百度翻译】。通过在命令窗口执行&#xff1a;composer或者&#xff1a;composer list得到 composer 的全部…

Ubuntu搭建联盟链,实现节点之间数据同步

安装go环境 从参考链接选择Linux版本的go的安装包 使用命令 mv go&#xff08;Tab补全&#xff09;/usr/local 移动go安装包到/usr/local目录下使用命令解压 sudo tar -xvzf go(Tab补全) 配置环境 sudo gedit ~/.profile export PATH$PATH:/usr/local/go/bin激活生效 sou…

火狐浏览器添加MetaMask钱包和本地开启私有链开发

火狐浏览器添加MetaMask钱包 因为对其配置了代理工具&#xff0c;所以直接使用谷歌引擎搜索MetaMask钱包即可第一次使用&#xff0c;立即开始设置 点击我同意&#xff0c;进行密码的创建 牢记助记词&#xff0c;助记词及其关键&#xff0c;将其存储在安全的地方 区块链-开发 M…

CLion导入用户自己的lib和头文件

文件的层级结构如上面所示对应的CMakeLists.txt配置文件如下面所示 cmake_minimum_required(VERSION 3.15) project(smart_shap)set(CMAKE_CXX_STANDARD 14)add_executable(${PROJECT_NAME} main.cpp )#target_link_directories(${PROJECT_NAME} PRIVATE ${PROJECT_SOURCE_DIR}…

东芝移动硬盘驱动_传输数据不用等,高速移动硬盘数据线畅享快传体验

不管你是设计师&#xff0c;摄影师亦或是办公一族&#xff0c;几乎都能用到电脑&#xff0c;而电脑里的文件如果很多的话&#xff0c;为了安全起见都会备份一份数据&#xff0c;以免电脑储存容量过大导致电脑卡顿。另一方面&#xff0c;为了保护数据防止丢失造成不必要的麻烦&a…

使用国密浏览器和使用Wireshark进行国密抓包

使用的软件 信密浏览器 密信浏览器发布Windows正式版 - 密信技术国密Wireshark GMSSL - 国密SSL实验室支持国密算法的网站 https://www.wotrus.com/ 流程操作 打开windows终端&#xff0c;使用命令ping沃通网站&#xff0c;找到这个网站的ip地址 ping www.wotrus.com打…

django框架学习文档_Python四大主流网络编程框架,你知道么?

高并发处理框架—— TornadoTornado 是使用 Python 编写的一个强大的可扩展的 Web 服务器。它在处理高网络流量时表现得足够强健&#xff0c;却在创建和编写时有着足够的轻量级&#xff0c;并能够被用在大量的应用和工具中。Tornado 作为 FriendFeed 网站的基础框架&#xff0c…

VS Studio报错无法解析的外部符号 _imp_XXXXXXXXX

出现字符_imp&#xff0c;说明不是真正的静态库&#xff0c;而是某个动态库的导入库&#xff0c;导入函数和自己不同名&#xff0c;所以加了字符_imp。比如说_imp_GetUserNameA就是GetUserNameA函数。会报这种错误的原因&#xff1a; 1、说明注册表函数没有相关的lib库&#xf…

hashmap put过程_阿里十年技术大咖,教你如何分析1.7中HashMap死循环

在多线程环境下&#xff0c;使用HashMap进行put操作会引起死循环&#xff0c;导致CPU利用率接近100%&#xff0c;HashMap在并发执行put操作时会引起死循环&#xff0c;是因为多线程会导致HashMap的Entry链表形成环形数据结构&#xff0c;一旦形成环形数据结构&#xff0c;Entry…

Socket代码实现服务端 和 客户端之间通信

服务端代码 // Socket_connection.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 // #ifndef UNICODE #define UNICODE #endif#define WIN32_LEAN_AND_MEAN#include <winsock2.h> #include <Ws2tcpip.h> #include <stdio.h> #incl…

python综合管理系统_Python-20 (信息系统-框架/循环/增删/综合应用)

# 1. 目标 这里我们通过简单案例的综合应用&#xff0c;了解框架的概念&#xff0c;感受循环、字符字典数据处理等基础点的应用场景 # 2. 框架 搭建一个人员信息管理系统的简单框架&#xff0c;初步感受框架的概念。 1> 主程序 -- cards_mian.py程序的主功能代码&…

本地搭建server和客户端使用端口进行数据通信,使用Wireshark抓取127.0.0.1环回地址并分析通信数据

本地搭建服务端和客户端 参考网址 Socket代码实现服务端 和 客户端之间通信_CHYabc123456hh的博客-CSDN博客server指定通信的端口是 5099client 使用的端口是动态变化的&#xff0c;因此在wireshark里面需要设定的抓取端口是 5099 使用wireshark开启抓包 参考链接 [tcp] Wir…

double operator[](int i)_java中double类型精度丢失问题及解决方法

原文链接&#xff1a;https://blog.csdn.net/yacolspace/article/details/78287394double类型数据加减操作精度丢失问题今天在项目中用到double类型数据加减运算时&#xff0c;遇到了一个奇怪的问题&#xff0c;比如120.2300.03&#xff0c;理论上结果应该是321.23&#xff0c;…

验证客户端和服务端可以传输经SM4加密的密文数据,从而验证发送数据已使用服务器密码机进行SM4加密,而不是随便的字符串乱码

前提操作 搭建客户端和服务端 Socket代码实现服务端 和 客户端之间通信_CHYabc123456hh的博客-CSDN博客使用wireshark进行数据的监听和测试https://blog.csdn.net/CHYabc123456hh/article/details/121929288 结论验证 使用在线SM4加密&#xff0c;输入明文 和 选择模式,生成…

Socket编程 涵盖代码和函数参数介绍

Socket是针对端系统&#xff0c;也就是用户主机上开发程序&#xff0c;不涉及网络设备(交换机、路由器)独立于网卡驱动层之上&#xff0c;不涉及硬件&#xff0c;即基于Packet Driver编程端&#xff1a;是指通信双方两台电脑 应用编程接口API 也就是两端 应用层内部的应用进程之…

springcloud阿里巴巴五大组件_如何无缝迁移 SpringCloud/Dubbo 应用到 Serverless 架构

简介&#xff1a; 本文分为三部分来介绍&#xff0c;分别介绍微服务应用迁移到 SAE 的优势&#xff0c;如何迁移 SpringCloud/Dubbo 应用到 SAE 上&#xff0c;以及针对 SpringCloud 应用迁移的实践演示。背景通过前面几节课程的学习&#xff0c;相信大家对于 SAE 平台已经有了…

frame中src怎么设置成一个变量_Go 语言设计哲学之七:变量声明须一致

Go 语言&#xff0c;使用变量之前需要先进行变量的声明。var s string “Golang"n : 666Go 语言有两类变量包级别(package varible)&#xff1a;在 package 级别可见的变量。如果是导出变量&#xff0c;该变量也可以被视为全局变量&#xff1b;局部变量(local varible)&a…

getdevicecaps在哪个头文件里_一招定胜负,while (true) 和 for (;;) 到底哪个更快

在JDK8u的jdk项目下做个很粗略的搜索&#xff1a;mymbp:/Users/me/workspace/jdk8u/jdk/src$ egrep -nr "for (s?;s?;" . | wc -l 369mymbp:/Users/me/workspace/jdk8u/jdk/src$ egrep -nr "while (true" . | wc -l 323并没有差多少。其次&#…