4000-520-616
欢迎来到免疫在线!(蚂蚁淘生物旗下平台)  请登录 |  免费注册 |  询价篮
主营:原厂直采,平行进口,授权代理(蚂蚁淘为您服务)
咨询热线电话
4000-520-616
当前位置: 首页 > 新闻动态 >
新闻详情
MyBatis学习笔记_jacksonary的博客-CSDN博客
来自 : CSDN技术社区 发布时间:2021-03-24
SQL映射文件增加MSSQL的SQL语句 并用databaseId指定数据库厂商的别名
 !--MySQL的查询语句--  select id getEmployeeById resultType employee databaseId mysql  select * from tbl_employee where id #{id} /select  !--同一SQL在不同数据库查询 这里指定去SQL Server中查询--  select id getEmployeeById resultType employee databaseId sql server  select * from employees where id #{id} /select 

然后运行面向接口的测试代码 通过控制台发现MyBatis发送的是mysql的SQL语句 然后通过更改environments标签的default属性值为default dev_mssql 再次运行 控制台打印的是MSSQL的语句。
【注意】这里除了在select标签中使用databaseId属性来指定SQL映射的哪种版本的数据库以外 还可以使用MyBatis内置参数_databaseId和结合if标签完成上面的工作 因为上述的方式必须要写两个select标签 并不符合程序员偷懒的好习惯 改造一下如下

 !--注意去掉原来标签中的databaseId属性--  select id getEmployeeById resultType employee  !--注意在数据库上厂商别名上加单引号 否则MyBatis不能识别--  if test _databaseId mysql  select * from tbl_employee where id #{id} /if  if test _databaseId sql server  select * from employees where id #{id} /if  /select  !--在MyBatis中必须配置数据库厂商的别名--  databaseIdProvider type DB_VENDOR  property name MySQL value mysql /  property name SQL Server value sql server /  /databaseIdProvider 
3.9 mappers标签

 通过该标签可以将SQL映射文件注册到全局配置文件中 用法如下

 mappers  mapper resource EmployeeMapper.xml /  /mappers 

当然在其子标签mapper是注册各个SQL映射文件的 这个子标签下主要有3个属性

resource 引用类路径下的SQL映射文件 url 引用网络路径或者磁盘路径下的SQL映射文件 class 直接引用接口。

前两种不作太多说明 主要关于第三种class属性做说明 如果直接引用接口 需要将接口和接口绑定的SQL映射文件必须在同一路径下并且两者的同名 但是更常规的做法是利用注解直接将SQL写在接口中的方法身上而不写mapper文件了 然后引用接口的类 比如

 Select( select * from tbl_employee where id #{id} )Employee getEmployeeById(int id);

但是又不太推荐这么去写 因为MyBatis好不容易将java代码和SQL语句分离开来 现在又给他搞进去 确实不太好 而且不利于复杂SQL语句后期的优化 但是又因为用注解的方式实在太方便了 所以可以将简单的、不太重要的SQL直接用注解去搞 复杂的SQL写在xml中。

 上面是单个SQL映射文件的注入 同时MyBatis也提供了批量映射文件的注册 只用如下的方式

 mappers  !--会注册该包下所有类--  package name 包名 /  /mappers 

但是这种适用于注解的方式 如果在xml的形式 就需要将SQL的映射文件和绑定的接口类放到同一包路径下并且同名。

4. SQL映射文件xxmapper.xml

 SQL映射文件是MyBatis的核心文件之一 主要用于SQL语句的存放和接口的绑定。在一开始的Demo中就涉及到了关于mapper文件的一些写法 该文件中的主体是 mapper 标签 里面还有其他的一些常用的标签

cache 配置接口的缓存cache-ref 引用其他接口的缓存resultMap 描述从数据库中加载出来的结果集parameterMap 已废弃sql 一个可重用的SQL语句 可以被其他语句引用 insert 插入操作的SQL映射 update 更新操作的SQL映射 delete 删除操作的SQL映射 select 查询操作的SQL映射

下面先对其中用的最多的增删改查标签搞一个小栗子

 ?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 名称空间 写绑定接口的全类名--  mapper namespace com.hhu.dao.EmployeeDao  !--id 唯一标识 就写成绑定接口中对应的方法名 resultType 返回值类型 即执行sql后的返回值想要怎么处理 封装成什么对象 #{id} 从方法传入的参数“id”获取传入sql语句的参数 select id getEmployeeById resultType com.hhu.entities.Employee  !--这里是查不到lastName属性的 MyBatis默认根据JavaBean中的属性名的方式去查找 数据库 如果属性和字段名对不上 那么就查不到  解决方法 在mapper文件属性名和字段名不一样地方 用JavaBean中的属性名做该字段的别名  不用通配符* 即可 select id, last_namemm lastName, gender,email from tbl_employee where id #{id} /select  !--这里更新的时候 使用parameterType指明传入参数类型是Employee对象  但是在SQL语句中我们需要的是这个对象中一些属性的时候 可以直接写 这个对象中的属性名即可 #{id}就是表示employee.id的意思--  update id upDateById parameterType employee  UPDATE tbl_employee SET last_NameMM #{lastName}, gender #{gender},email #{email} WHERE id #{id} /update  delete id deleteById  DELETE FROM tbl_employee WHERE id #{id} /delete  有时候用户在做数据的写操作的时候 希望得到一个结果的反馈  写入成功返回true 写入失败返回false; MyBatis在涉及到写操作的删、除、改三种操作是允许返回true或者false的, 直接在接口中将这些方法的返回值定义为boolean即可 但是在mapper文件 中标签中不需要指定返回值类型。原理是根据SQL语句影响的行数来 封装返回值的 如果影响的行数为0则返回false 如果影响的行数大于0则返回true insert id saveEmp parameterType employee  INSERT INTO tbl_employee(last_nameMM,gender,email)VALUES (#{lastName}, #{gender}, #{email}) /insert  /mapper 

 在看完常用的增删改查的操作后 再来看下sql标签 他是用来抽取可重用的SQL语句元素 有点类似于模板的意思 一般都和include一起出现 就是一处定义 处处可引用 看一下小栗子

 !--抽取可重用的SQL--  sql id insertSql  last_NameMm, gender, email /sql  insert id insertTest  INSERT INTO tbl_employee( !--引用外部定义的SQL--  include refid insertSql /include  ) VALUES (#{lastName}, #{gender}, #{email}) /insert 

同时在include标签中可以自定属性 反过来在sql中使用 注意使用形式${属性} 比如

 !--抽取可重用的SQL--  sql id insertSql  !--使用include标签中自定义的属性 注意形式--  last_NameMm, gender, email, ${testProperty} /sql  insert id insertTest  INSERT INTO tbl_employee( !--引用外部定义的SQL--  include refid insertSql  !--自定义属性--  property name testProperty value abc /  /include  ) VALUES (#{lastName}, #{gender}, #{email}, #{testABC}) /insert 

那么最后拼接出来的SQL语句为

INSERT INTO tbl_employee(last_NameMm, gender, email, abc) VALUES (?,?,?,?)

如果希望写入操作的方法返回boolean mapper中正常写 接口中指明返回类型 比如public boolean saveEmp(Employee employee);在返回的时候MyBatis会直接将SQL语句影响的行数转成boolean类型的返回值。在跑测试案例的时需要手动提交sqlSession 上面案例中我们过去Session的方式是sessionFactory.openSession() 这种方式获取的Session是不会自动提交的 关闭Session前 必须先进行session.cmoit()的执行 之前不写是因为只是用来对数据库进行读操作 但凡涉及到数据库的写操作就必须进行提交 否则MySQL只是发送SQL语句 但是这个SQL不会落实到数据库上对其造成影响 但是可以通过sessionFactory.openSession(true)的方式获取可以自动提交的Session。

4.1 获取自增主键

 在实际开发中 保存一条记录时 可能想要获取它的id 由于id在数据库中设置的是自增 所以一般不会传进去 比如下面的

Employee employee new Employee();employee.setLastName( testInsert2 );employee.setEmail( insert2 163.com );employee.setGender(0);System.out.println(employeeDao.saveEmp(employee));System.out.println( 新增主键 employee.getId());//涉及到写操作的行为必须手动提交 否则不会提交 读操作到没有什么影响sqlSession.commit();

就这样去做 获取的新增主键为0 必须在mapper文件对应的标签设置使用主键生成器 并且将这个生成的id绑定到JavaBean中的某个属性上 在mapper文件使用useGeneratedKeys true 开启此功能 使用keyProperty 属性名 将获取的主键绑定到javaBean的属性上即可

 insert id saveEmp parameterType employee useGeneratedKeys true keyProperty id  INSERT INTO tbl_employee(last_nameMM,gender,email)VALUES (#{lastName}, #{gender}, #{email}) /insert 

再次测试上面的案例即可获取到新增id的值

4.2 获取非自增主键

 上面一小节是通过数据库将主键设置为自增的方式 id属性可以直接不传入 但是对于不支持id自增的数据库(比如Oracle数据库) 怎么来做呢 比如id通过序列的方式生成 那么怎么来获取id。传入的保存记录对象照样不用传id属性 我们在SQL语句上做文章 下面以序列id为例看一下MyBatis是如何完成插入操作的
首先到数据库中查询用户的序列表 select * from user_sequences; 可以查看用户所有的序列表的 然后选择对应表的序列表 这里以表employees主键对应的序列表EMPLOYEES_SEQ为例 然后xml中如下

 insert id saveEmp databaseId oracle  !--首先去序列表中查询下一个序列值 然后绑定到JavaBean的id属性上 并且通过order属性指定这个SQL在主体SQL(即查询SQL)前执行即可。 selectKey keyProperty id order BEFORE  SELECT EMPLOYEES_SEQ.nextval FROM dual /selectKey  !--执行主体SQL时可以直接取上面SQL查询并封装在对象id属性中--  INSERT INTO employees(id,last_name,gender,email) VALUES (#{id},#{lastName}, #{gender}, #{email}) /insert 
4.3 MyBatis的传参处理

 MyBatis中对于参数的处理 有多种情况 一一做说明

对于单个参数 MyBatis不会做处理 约定俗成接口方法中参数名是什么就写成#{参数名}的形式 比如
public Employee getEmployeeById(int id);

那在mapper中写的映射语句为

 select id getEmployeeById resultType employee  select * from tbl_employee where id #{id} /select 

其实这里只有一个参数 不管你接口方法中参数名是什么 在mapper文件中可以任意写 甚至可以瞎写 比如上述的映射语句可以写成

 select id getEmployeeById resultType employee  select * from tbl_employee where id #{hh} /select 

只不过写成接口方法中的参数名好理解些。

对于多个参数 MyBatis会自动帮我们处理(封装成一个Map) 其中Map的Key为依次为param1、param2、param3……以此类推 接口方法中传入几个参数 value就是调用接口时传入的具体内容 就这样封装 然后在mapper中获取其中的属性时就用#{Key名}的发方式来获取封装好的value 这里首先做一个说明 MyBatis封装的多参数Map的名字叫做_parameter 这也是MyBatis的内置参数 在mapper文件中可以直接使用它来判断诸如传入的多参数对象(这个Map对象可以是MyBatais自动封装的 也可以是一个JavaBean对象)是否为空 比如下面的
public Employee getByIdAndLastName(int id, String lastName);

然后在mapper文件中获取

 select id getByIdAndLastName resultType employee  !--这里参数完整的写法应该为#{_parameter.param1} 但是通常会省去_parameter--  SELECT * FROM tbl_employee e WHERE e.id #{param1} AND e.last_namemm #{param2} /select 

但是在实际开发中 如果有多个参数 以param1、param2……这种方式出现在SQL语句中确实不能起到见名知意的效果 所以这里可以在接口方法参数前面使用 Param( 别名 )注解 这样就可以指定MyBatis在封装Map时的Key 最后在mapper中取参数的时候就可以用我们自己指定的别名来获取 而不用param1、param2这种方式来获取 比如下面

public Employee getByIdAndLastName( Param( id ) int id, Param( lastName ) String lastName);

mapper中获取

 select id getByIdAndLastName resultType employee  SELECT * FROM tbl_employee e WHERE e.id #{id} AND e.last_namemm #{lastName} /select 

 对于多个参数的处理 除了使用的上面MyBatis自动封装的Map 我们还可以手动自己封装Map 比如上面的getByIdAndLastName方法 其实他没有必要封装 因为传入的参数比较少 使用MyBatis自动封装就挺好 这里纯粹是为了演示手动封装参数的方法而为之

public Employee getByMap(Map map);

mapper中

 !--这里的#{}中的别名按照map中传入的key值来取--  select id getByMap resultType employee  SELECT * FROM tbl_employee WHERE id #{id} and last_namemm #{lastName} /select 

调用测试

Map String, Object map new HashMap();map.put( id , 6);map.put( lastName , jack );Employee e employeeDao.getByMap(map);System.out.println(e);

【注意】这里的手动封装的Map中的key值就是我们在mapper中使用的别名。当然如果传入的参数刚好完全是JavaBean的几个属性(如果id可以不带id) 那么接口传入参数可以直接传入JavaBean对象 在mapper中获取的它的属性时 直接使用#{属性名}的方式来获取即可。

 除了上述的注意的地方还有几个需要注意的点

/*MyBatis自动封装 mapper获取方式 * id: #{id}或者#{param1}* name: #{param2}public Employee getEmp( Param( id )int id, String name);/*MyBatis自动封装 mapper获取方式 * id: #{param1}* name: #{param2.name}而不是直接用#{name}public Employee getEmp(int id, Employee e);/*MyBatis对Collection(List、Set)和数组有特殊的封装方式 * 虽然也是封装到Map中 但是Map的Key的名字变了 可以统一* 使用“collection” 或者 * List使用“list” 如果取list的首个元素可以使用#{list[0]}* 数据使用“array”public Employee getById(List Integer ids);
4.4 mapper中取值方式

 在SQL映射文件中 我们通常是以#{}形式来获取传入的参数 但是在MyBatis中也是可以用${}的形式来取值的 两者虽然都能达到我们所需要的结果 但是差异还是很大的。

#{}是以预编译的形式将参数设置到sql语句中 PreparedStatement可以防止sql注入 ${}是以拼接sql语句的形式直接将参数搞到SQL语句上 有安全问题。

比如举个栗子

 select id getByMap resultType employee  SELECT * FROM tbl_employee WHERE id ${id} and last_namemm #{lastName} /select 

我们将参数封装好调用接口 从控制台的输出可以看到MyBatis的发送的SQL语句如下

SELECT * FROM tbl_employee WHERE id 6 and last_namemm ?

和上面所说的一样 ${}取值id的参数直接拼接到了SQL语句上 而#{}取值的lastName则是以占位符?的形式在SQL语句中 所以一般情况下我们都是使用#{}。

 【注意】那还有一种取值方式在哪种场景下使用呢 原生JDBC不支持占位符的地方我们就必须用${}进行SQL语句的拼接了(比如数据库的表名 根据某个字段排序 里面的“字段”和排序的方式名都是不支持占位符的) 他就是不支持占位符的 那此时就必须使用${}的方式了 使用’#{} 会报错 比如公司的员工的薪资表按照“年份_salary”的方式命名的 我们需要动态的查询薪资表的记录(有时查2016_salary有时需要查2018_salary表) 此时我们可以这样写

public Salary getSalary(int year,String user);

在mapper中就可以这么写

 select id getSalary resultType salary  select * from ${param1}_salary where username #{param2} /select 

调用接口getSalary(2015, jack )此时MyBatis发送的SQL语句为

select * from 2015_salary where username ?

是完美符合我们的要求的。

4.5 关于传入参数为null的情况

 在MyBatis中 如果方法参数传入null 那么它会自动应映射为jdbcType类中的OTHER(Types.OTHER)的形式即OTHER类型 大部分数据库是可以识别的(比如MySQL、Sql Server) 但是在有些数据库不能识别MyBatis处理null的OTHER类型(比如Oracle数据库就不能识别) 这个时候就需要在传值的时候指定如果参数传入为null MyBatis应该将它转成JDBCType中什么类型 正常情况传入的null转成NULL都是可以被识别的(Oracle和MySQL以及MSSQL)。有两种用法如下

在mapper文件中直接对指定传入的参数进行null值转换的处理
 !--比如在保存Employee时 传入的eamil为null时, MyBatis会自动将其转成Oracle数据库可以识别的NULL类型 而不是转成默认的OTHER类型 insert id saveEmp parameterType employee databaseId oracle  INSERT INTO employees(last_name,gender,email) VALUES (#{lastName}, #{gender}, #{email, jdbcType NULL}) /insert 
当然 还可以直接在MyBatis的全局配置文件中的 settings 中进行设置 这是针对所有的null设置 而不是像第一种方法对某个字段进行null的处理
 settings  setting name jdbcTypeForNull value NULL /  /settings 

可以如果配置的话建议直接用第二种方式 将全局null值在转换的时候转成NULL而不是OTHER。

4.6 关于接口方法不同返回值类型的处理

 在接口的查询的方法中会有返回值 也有可能没有返回值 返回值可以是一个基本数据对象 也可以是一个对象(pojo对象直接指定为设定的别名) 下面对接口中不同方法的不同返回值的类型的处理做一个探讨 在mapper映射文件中存在返回值的只有 select 标签(除了MyBatis将增、删、改三种操作影响的行数转成boolean类型的返回值) 返回值可以用 select 标签中的resultType属性指定(指定为别名或者全类名)或者resultMap自定义封装 如果返回的是集合类型 那么指定为集合中元素的类型 注意resultType属性不能和resultMap属性同时使用。

 比如返回的是一个List对象 据上所述 可以如下

public List Employee getEmps();

在mapper中的返回值类型需要指定为List集合中存放元素的类型 这个方法的映射就是Employee这个JavaBean的实体类型。

 select id getEmps resultType employee  select * from tbl_employee /select 

 如果接口的返回值类型是Map类型 这里需要注意一下 如果返回值就是由一条记录里面所有属性都单独封装起来的多个Map 此时key就是列名 value就是对应的属性值 比如下面的

public Map String, Object getEmpByIdReturnMap(int id);

mapper文件中为

 !--注意这里的返回值类型写map,MyBatis对常用的数据类型已经起了别名--  select id getEmpByIdReturnMap resultType map  SELECT * FROM tbl_employee WHERE id #{id} /select 

最后调用接口返回值为Map类型 JavaBean的每个属性在数据库表中对应的列名都被MyBatis封装到Map中 Key为属性名 value就是查询出来的对应属性值 上面是将一个JavaBean对象的各个对应表的字段名封装到多个Map中。但是更好的做法是直接将javaBean作为一个对象封装到一个Map中 而不是将各个字段单独封装成多个Map 就像Map Integer, Employee 的形式 以Employee的主键id作为Map的Key 如下

//这要需要指定Map的key是什么 这里是id 当然也可以是其他属性//需要注意下key的唯一性 MapKey( id )public Map Integer, Employee getEmps();

mapper文件

 !--对于集合而言 resultType永远都是集合里面元素的类型--  select id getEmps resultType employee  SELECT * FROM tbl_employee /select 

 返回值除了上述的resultType指定返回值类型外(基本用于MyBatis提供的自动封装) 还可以使用一个非常重要的resultMap属性指定自定义结果集。如果JavaBean的属性名和数据库对应的列名不一致 MyBatis是无法自动封装的 出现这种情况 一般有以下几种方法

在写SQL语句时指定别名(如 select last_name lastName) 开启下划线驼峰命名法( setting name mapUnderscoreToCamelCase value true / ) 前提是满足条件 如 数据库C_Action JavaBean中的cAtion 返回值使用resultMap来自定义返回集 指定Employee中的属性对应数据库中的哪个字段。

 在开始之前先把resultMap标签中注意点说一下 和 mapper 标签一样 resultMap下的子标签必须按照一定的顺序排列 否则报错 正确顺序如下 constructor? id* result* association* collection* discriminator?。

 下面具体看一下resultMap的用法

//接口中的方法照常写public Employee getEmployeeById(int id);

mapper文件中使用自定义类型

 !--自定封装的规则 id 自定义的封装类型的标识符 方便后面引用 type 指定自定义封装的JavaBean的类 可以用全类名也可以使用别名 resultMap id MyEmp type employee  !--指定封装类型的主键  column 数据库中的列名 property JavaBean中与数据库列名相对应的属性名 这里自定义封装类型 通常是把所有的JavaBean属性都封装 但是注意 那些不符合MyBatis自动封装的属性是不能被自动封装的  比如 属性名和列名相同的(不分大小写) 以及开启下划线驼峰命名规则 后 刚好可以完成这种转换的才能自动封装 id column id property id /  !--result用于定义非主键列名和javaBean的属性名的对应关系--  result column last_nameMm property lastName /  result column gender property gender /  result column email property email /  /resultMap  !--这里的返回值类型用resultMap指定为自定义的类型 不能使用resultType指定了--  select id getEmployeeById resultMap MyEmp  select * from tbl_employee where id #{id} /select 
4.7 关于级联属性的查询处理

 在实际开发中会遇到不少级联属性的查询 小栗子(Employee和Department Employee中持有Department对象)

 第一部分以多对一的关联关系为例 直接看下两个JavaBean

public class Employee { private int id; private String lastName; private int gender; private String email; private Department dep; //getter and setter as well as toString(no dep)public class Department { private int dId; private String dpName; //getter and setter as well toString

数据库的表结构为 tbl_departments和tbl_employee
\"这里写图片描述\"
这里主要是针对在查询Employee对象时怎么将它关联的Department属性查询出来。

 看一下具体的实现 第一种方式 自定义封装返回类型 mapper中如下

 resultMap id EmpWithDep type employee  id column id property id /  result column last_nameMn property lastName /  result column gender property gender /  result column email property email /  !--级联属性直接用Employee里面的“dep”去获取关联的Department属性  即以“属性.属性”的方式来关联Department对应的表中的列名 result column d_id property dep.dId /  result column dp_Name property dep.dpName /  /resultMap

本文链接: http://jacksonisac.immuno-online.com/view-702569.html

发布于 : 2021-03-24 阅读(0)
公司介绍
品牌分类
制药的
联络我们
服务热线:4000-520-616
(限工作日9:00-18:00)
QQ :1570468124
手机:18915418616
官网:http://