首页 > 其他分享 >Mybatis核心技术

Mybatis核心技术

时间:2022-12-19 11:36:27浏览次数:38  
标签:username 语句 核心技术 mybatis sql Mybatis id SELECT


介绍

MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。     MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。

Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatement、CallableStatement)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。

 

使用原生jdbc出现的问题

 

1、     数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链接池可解决此问题。

2、  Sql语句在代码中硬编码,造成代码不易维护,实际应用sql变化的可能较大,sql变动需要改变java代码。

3、  使用preparedStatement向占有位符号传参数存在硬编码,因为sql语句的where条件不一定,可能多也可能少,修改sql还要修改代码,系统不易维护。

4、  对结果集解析存在硬编码(查询列名),sql变化导致解析代码变化,系统不易维护,如果能将数据库记录封装成pojo对象解析比较方便。

Mybatis架构

Mybatis核心技术_DAO

 

 

Mybatis配置

SqlMapConfig.xml:  mybatis的全局配置文件,配置了mybatis的运行环境等信息。
Mapper.xml:  sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在sqlMapConfig.xml中加载。


#{}占位符:占位
如果传入的是基本类型,那么#{}中的变量名称可以随意写
如果传入的参数是pojo类型,那么#{}中的变量名称必须是pojo中的属性.属性名(user.username)

${}拼接符:字符串原样拼接(有sql注入的风险)
如果传入的是基本类型,那么${}中的变量名必须是value
如果传入的参数是pojo类型,那么${}中的变量名称必须是pojo中的属性.属性名(user.username)
注意:使用拼接符有可能造成sql注入,在页面输入的时候可以加入校验,不可输入sql关键字,不可输入空格
注意:如果是取简单数量类型的参数,括号中的值必须为value
例: select * from user where username like '%${value}%'
   可以这样写来解决sql注入:select * from user where username like '%’ #{name}’%'(开发经常使用)

 

入门

注意本程序只是为了理解mybatis的使用,实际开发中可能不这样使用

SqlMapConfig.xml配置:

(并不固定,可以写别的名称)mybatis基本配置

<?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>
<!-- 和spring整合后 environments配置将废除-->
<environments default="development">
<environment id="development">
<!-- 使用jdbc事务管理-->
<transactionManager type="JDBC" />
<!-- 数据库连接池-->
<dataSource type="POOLED ">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" />
<property name="username" value="root" />
<property name="password" value="root" />
</dataSource>
</environment>
</environments>
<!—关联映射-->
<mappers>
<mapper resource="sqlmap/User.xml"/>
</mappers>
</configuration>

经测验映射文件最好和核心配置文件在一个文件夹下

properties(属性)
settings(全局配置参数)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境集合属性对象)
environment(环境子属性对象)
transactionManager(事务管理)
dataSource(数据源)
mappers(映射器)

Mapper配置文件

配表与pojo关系,以及sql

<!-- 根据id获取用户信息 -->
<select id="findUserById" parameterType="int " resultType="cn.itcast.mybatis.po.User" >
select * from user where id = #{id}
</select>

id: sql语句的唯一标识,与dao接口中的方法名一致

parameterType:定义输入到sql中的映射类型(请求参数),#{id}表示使用preparedstatement设置占位符号并将输入变量id传到sql。id 可以用任意字符代替并不固定
resultType:定义结果映射类型(返回值)。

注意:当返回值是List集合时他的类型就是泛型的类型

 

mybatis支持别名:

别名

映射类型

_byte

byte

_long

long

_short

short

_int

int

_integer

int

_double

double

_float

float

_boolean

boolean

string

String

byte

Byte

long

Long

short

Short

int

Integer

integer

Integer

double

Double

float

Float

boolean

Boolean

date

Date

decimal

BigDecimal

bigdecimal

BigDecimal

map

Map

动态Sql

If

通过mybatis提供的各种标签方法实现动态拼接sql
原始sql语句:

SELECT * FROM USER WHERE username  LIKE  '%王%'  AND  sex= ’2’ 
Mybatis中简单的sql语句: 

<select id="findUserByNameAndSex" parameterType="user" resultType="user">
SELECT * FROM USER WHERE username LIKE '%${username}%' AND sex=#{sex}
</select>

trim

<trim prefix="(" suffix=")" prefixOverrides="and" ></trim>

 

前缀'and' 被'('  替换

  prefix:前缀覆盖并增加其内容 不写的话默认替换为空

   suffix:后缀覆盖并增加其内容 不写的话默认替换为空

   prefixOverrides:前缀判断的条件

         suffixOverrides:后缀判断的条件

使用动态sql语句: 

where

<select id="findUserByNameAndSex" parameterType="user" resultType="user">
SELECT * FROM USER
<where><!-- 他能自动判断将where关键字后的and去掉 -->
<if test="username!=null and username!=''">
AND username LIKE '%${username}%'
</if>
<if test="sex!=null and sex!=''">
AND sex=#{sex}
</if>
</where>
</select>

<where> 可以自动去除sql语句where关键字后的and关键字

 

Foreach

向sql传递数组或List,  mybatis使用foreach解析,可以做批量处理
Sql语句: 

SELECT * FROM USER WHERE id IN (1,10,16)
使用foreach赋值:

<select id="findUserByIds" parameterType="queryVo" resultType="user">
SELECT * FROM USER
<where>
<foreach collection="ids" open="id IN (" close=")" item="id" separator=",">
#{id}
</foreach>
</where>
</select>

 

foreach:循环传入的集合参数
collection:传入的集合的变量名称(要遍历的值)
item:每次循环将循环出的数据放入这个变量中
open:循环开始拼接的字符串
close:循环结束拼接的字符串
separator:循环中拼接的分隔符
批量修改实例:
sql:

UPDATE rc_notify_queue   SET  queue_status = 'E',execute_time=NOW() WHERE notify_queue_Id IN (3,22,11)

 

<!-- 批量修改 -->
<update id="updateByList" parameterType="java.util.List" >
UPDATE rc_notify_queue SET queue_status = 'E',execute_time=NOW()
<where>
<foreach collection="list" open="notify_queue_Id IN (" close=")" item="notify" separator=",">
#{notify.notifyQueueId}
</foreach>
</where>
</update>

 

一个大神朋友写的批量修改:

 

Mybatis核心技术_xml_02

 

 

​​choose​​

if标签是与(and)的关系,而 choose 是或(or)的关系。

有时候我们并不想应用所有的条件,而只是想从多个选项中选择一个。而使用if标签时,只要test中的表达式为 true,就会执行 if 标签中的条件。MyBatis 提供了 choose 元素。choose标签是按顺序判断其内部when标签中的test条件出否成立,如果有一个成立,则 choose 结束。当 choose 中所有 when 的条件都不满则时,则执行 otherwise 中的sql。类似于Java 的 switch 语句,choose 为 switch,when 为 case,otherwise 则为 default。

sql片段

Sql中可将重复的sql提取出来,使用时用include引用即可,最终达到sql重用的目的
将where条件抽取出来:

<sql id="user_where">
<where>
<if test="username!=null and username!=''">
AND username LIKE '%${username}%'
</if>
</where>
</sql>

引用: 

<select id="findUserByNameAndSex" parameterType="user" resultType="user">
SELECT * FROM USER
<include refid="user_where"/>
</select>

注意:也可在sql标签中也可以只放if标签

 

<if test="_parameter != null" >

_parameter : 参数的引用

关联查询:

多表查询返回的数据是两个表中的数据这样就出现了数据封装的问题
解决方案一:创建一个有两个表的数据类
<!-- 一对一:自动映射 -->

<!-- 一对一:自动映射 -->
<select id="findOrdersAndUser" resultType="customOrders">
SELECT * FROM USER a , orders b WHERE a.id = b.user_id
</select>

和普通方法是一样的,只是要多创建一个po类

解决方案二:不需要新建po类只要在映射文件中配置:

<resultMap type="orders" id="orderAndUserResultMap">
<id column="id" property="id"/>
<result column="userId" property="user_id"/>
<result column="number" property="number"/>
<result column="createtime" property="createtime"/>
<result column="note" property="note"/>
<!-- 封装对象属性 -->
<association property="user" javaType="com.itheima.pojo.User">
<id column="id" property="id"/>
<result column="username" property="username"/>
<result column="sex" property="sex"/>
<result column="address" property="address"/>
<result column="birthday" property="birthday"/>
</association>
</resultMap>

使用:

<select id="findOrdersAndUser2" resultMap="orderAndUserResultMap">
SELECT * FROM USER a , orders b WHERE a.id = b.user_id
</select>

Type: po类的权限定名,这里使用的是别名
Id: 主键
Result: 普通属性
Column:     po类属性
Property:    表字段名
Association: 引用数据类型
Property:    在po类中的名称
JavaType:   全限定名
分两块,第一块使用resultMap标签封装数据,第二块在select中使用resultMap引用封装好的数据;

这种放法优于第一种方法,第一种方法再写po类增加了工作量,也不便于以后对数据的使用,也不能表现表与表之间的关系

 

封装map集合:

返回结果集类型: resultType="java.util.Map"
查询后返回的结果:List<Map>
将数据库中每条数据:字段和值按照 key(字段名),value(字段值) 封装到hashMap集合中
然后在把Map集合封装到Llist集合中


将一条数据封装成map集合:

使用resultMap封装数据

<resultMap type="java.util.Map" id="orderAndUserResultMap"> <id column="cid" property="cid"/> <result column="cust_name" property="cust_name"/> <result column="cust_type" property="cust_type"/> <result column="cust_phone" property="cust_phone"/> <result column="cust_address" property="cust_address"/> <result column="custlink_user" property="custlink_user"/> </resultMap> <select id="findCustList" parameterType="cn.itheima.pojo.QueryVo" resultMap="orderAndUserResultMap"> SELECT * FROM s_cust </select>

Column就是map集合的key Property数据库传来的数据注意:property值对应数据库中的字段值这种方式只能获取一条数据

Spring整合mybatis 

SqlMapConfig.xml配置:

<typeAliases>
<!-- 包扫描 -->
<package name="com.mybatis.pojo"/>
</typeAliases>
<!-- 关联映射 -->
<mappers>
<mapper resource="User.xml"/>
<!-- 包扫描 -->
<package name="com.mybatis.dao"/>
</mappers>

其余交个spring管理
ApplicationContext.xml
配置dataSource
配置sqlSessionFactory

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 指定mybatis核心配置文件 -->
<property name="configLocation" value="classpath:SqlMapConfig.xml"></property>
<!-- 指定会话工厂使用的数据源 -->
<property name="dataSource" ref="dataSource"></property>
</bean>



原生Dao实现:原生Dao实现和普通类的配置一样
Mapper接口代理:
方式一:

<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean"> 
<!-- 配置mapper接口的全路径名称 -->
<property name="mapperInterface" value="com.mybatis.dao.UserMapper"></property>
<property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
</bean>

注意:
Bean标签中class属性是mybatis提供的接口代理对象所以是固定的
name="mapperInterface"和name="sqlSessionFactory" 代理对象中的属性也是固定的

方式二:包扫描

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="cn.mybatis.dao"></property>
</bean>

注意:
  使用包扫描的方式批量引入Mapper扫描后引用的时候可以使用类名,首字母小写.
指定要扫描的包的全路径名称,如果有多个包用英文状态下的逗号分隔
 

标签:username,语句,核心技术,mybatis,sql,Mybatis,id,SELECT
From: https://blog.51cto.com/u_10176086/5951815

相关文章

  • java核心技术学习笔记——synchronized底层如何实现?什么是锁的升级、降级?
    在Java6之前,Monitor的实现完全是依靠操作系统内部的互斥锁,因为需要进行用户态到内核态的切换,所以同步操作是一个无差别的重量级操作。现代的(Oracle)JDK中,VM对此进......
  • SpringMVC核心技术
    入门程序Web.xml(前端控制器)配置:        在web.xml中添加DispatcherServlet的配置。         <servlet><servlet-name>springmvc</servlet......
  • mybatis插入的字符串主键变成了0?
    记录一个神奇的事情,之前没这么用过。本来我插入的字符主键000000,结果插入的SQL显示0。离谱不?    直接说原因,我插入的主键本来有值,但sql写了主键赋值的操作。就......
  • MyBatis实现增删改查
    目录新建项目准备相关配置新建包和相关类增删改查实现根据id查询用户根据密码和名字查询用户给数据库增加一个用户修改用户的信息根据id删除一个用户小结模糊语句新建项目......
  • MyBatis:查询的数量与直接在 MySQL 查询的数量不一致
    这是我在MySQL中直接查询的结果:一共有4条数据。这是MyBatis查询出来的结果:查询出来只有2条数据,这和我在MySQL中直接查询的数量严重不一致。在网上也查询了......
  • Mybatis:通过自动映射解决一对一映射字段
    像是下面这样的,如果真要一个个地去把reulst子标签写出来,有点不太现实,还好mybatis提供了autoMapping,可以作用在association和resultMap标签上:<resultMapid="mapO......
  • Mybatis:解决实体类驼峰命名与数据库字段之间映射的问题
    数据库的命名规则都是_来隔开单词,Java中是驼峰命名法,所以导致实体类与数据库字段不一致,从而返回的结果有部分会被丢失。一、可以在mapper.xml中通过resultMap来解决:......
  • MyBatis核心配置文件详解
    目录environmentstransactionManagerDataSource引入jdbc.propertiestypeAliasessettings下划线转驼峰延迟加载MappersIDEA核心配置模板及解释environments可以配置多个......
  • Mybatis-Spring
    Mybatis-Spring版本关系图当前环境JDK8Mybatis-Spring2.1.0Mybatis3.5.11Log4j1.2.17lombok1.18.24SpringFramework5.3.20Dbcp2.9.0......
  • 基于Mybatis-Plus实现Geometry字段在PostGis空间数据库中的使用
    背景在OGC标准中,通常空间字段是由Geometry类型来表示。而一般编程语言中是没有这种数据类型的。以java为例,怎么操作这些数据,满足业务需求呢?跟着本文一起来学习吧。今天介绍......