mybatis中字段名与实体属性名不一样的情况下插入数据的方法,在xml配置文件里sql语句应该怎么写?

mybatis中字段名与实体属性名不一样的情况下插入数据的方法,在xml配置文件里sql语句应该怎么写?,第1张

查询语句是 MyBatis 中最常用的元素之一,本文涉及mybatis的单表查询 *** 作,关联表有关的查询会后续补充。
巧妇难为无米之炊,要想从数据库中表中取出数据并转化为javaBean,所以,我们要先准备javabean以及与其对应的数据表。
javaBean:
public class President {
private int id;
private String name;

@Override
public String toString() {
return "President [id=" + id + ", name=" + name + "]";
}
//get set 方法
}
创建两个对应的数据库表,并插入两条数据:
create table president1(
p_id int not null auto_increment primary key,
p_name varchar(50) not null
);
insert into president1(p_name) values('lily'),('Tom');
create table president2(
id int not null auto_increment primary key,
name varchar(50) not null
);
insert into president2(name) values('lily'),('Tom');
创建两个数据库是为了测试两个不同的查询状况,
数据库字段名与实体类属性名相同
从sql表可以看出president2的字段名与javabean:President的属性名完全相同,这种情况下mybatis的select *** 作非常简单:
<!-- 从表 president2中查询-->
<select id="getPreByIdPresident2" parameterType="int" resultType="President">
select from president2 where id=#{id}
</select>
此时mybatis运用反射机制会将查询返回的结果(id,name)封装成President对象。
如果从表president1中查询,同样采用上面的sql语句
<!-- 从表 president1中查询-->
<select id="getPreByIdPresident1" parameterType="int" resultType="President">
<span style="white-space:pre"> </span>President p1 = sessionselectOne(statement+"getPreByIdPresident1", 1);
<span style="white-space:pre"> </span>Systemoutprintln("表president1中查询"+p1);
</select>
此时如果用getPreByIdPresident1进行查询,返回的结果会是null,我们将上面的sql语句在mysql中执行下:
有结果返回,但是返回的字段名为(p_id,p_name)这种结果mybatis在解析时无法与President类对应。多数情况下实体类属性名与数据库表的字段名都会有差异,这种情况如果mybatis不能处理也就太low了。
数据库字段名与实体类属性名不相同
mybatis针对该种情况有两种解决方法,但是归根到底都是同一种实现。
Method1:定义一个ResultMap将数据库字段名与实体类属性名做个映射
我们欲从表president1中查询数据,此时的mapper配置如下:
<resultMap type="President" id="getFromPresident2">
<!-- 主键必须用id标签映射,其他的用非集合用result映射 集合类用collection映射 -->
<!-- column为数据库字段名,property为实体类属性名 -->
<id column="p_id" property="id" />
<result column="p_name" property="name" />
</resultMap>
<select id="getPreByIdPresident1Method1" resultMap="getFromPresident2">
select from president1 where p_id=#{id}
</select>
首先定义了一个resultMap,将数据库表的字段名与实体类属性名做了一一对应,其中type为实体类(此处运用的类别名),id为了在select标签中引用映射结果。
在select标签中并没有用resultType属性,而使用了resultMap,即为上面定义的resultMap,mybatis会根据resultMap中的映射关系去构造President
Method1:直接在sql语句中使用别名
<!-- 从表 president1中查询 -->
<select id="getPreByIdPresident1Method2" resultType="President">
select p_id id,p_name name from president1 where p_id=#{id}
</select>
这种方法会查到实际的数据,这种方法与字段名和属性名相同都是基于相同的原理:MyBatis 会在幕后自动创建一个 ResultMap,基于属性名来映射列到JavaBean 的属性上。即mybatis底层都是通过创建ResultMap来进行关系的映射,与method1原理相同。。

经过测试,批量 *** 作数组时,总是提示出错,JavautilArray
找不到
可能要携程ArrayList就行了,但是我插入的数据
是String
[]
ids=strsplit(",");这种形式的,不能用ArrayList吧,反正这个没成功,后来我又把str转换成
List,才可以用collection=list来批量 *** 作。
List
a=ArraYlsitasList(str);
在使用foreach的时候最容易出错的就是collection属性,该属性是必须指定的,在不同情况
下,该属性的值是不一样的,主要有一下3种情况:
1
如果传入的是单参数且参数类型是一个List的时候,collection属性值为list
2
如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array
3
如果传入的参数是多个的时候,我们就需要把它们封装成一个Map了,当然单参数也可以封装成map,实际上如果你在传入参数的时候,在breast里面也是会把它封装成一个Map的,map的key就是参数名,所以这个时候collection属性值就是传入的List或array对象在自己封装的map里面的key
我采用mybatis直接将数组当作参数传入总是出现错误,说找不到参数,也按照上述的条件一一尝试结果还是不行,我想可能出现这个问题的原因是mybatis的版本问题。后来采用传入一个实体,在实体里面定义数组的方法。然后 *** 作,这样就不出错了。此方法虽为下册,但也可以应付一些关键问题。

想象一下你在淘宝,在购买东西后会有个订单支付的页面,下单后用户和订单就关联起来了,同时订单有一个唯一的编号叫订单号。用户表和订单表的关系为,一个用户有多个订单,一个订单只从属于一个用户

一对一查询的需求:查询一个订单,与此同时查询出该订单所属的用户

即 order对user是一对一的,反过来,user对order是一对多的

select ,oid oid from orders o,user u where ouid=uid

这个查询结果看起来很怪,有很多个id,不着急,后面我们在进行配置文件的配置的时候可以将id忽略。

User和以前一样

测试

或者通过
<association> 标签配置user

用户表和订单表的关系为,一个用户有多个订单,一个订单只从属于一个用户
一对多查询的需求:查询一个用户,与此同时查询出该用户具有的订单

select ,oid oid from user u,orders o where uid = oid

打印结果

再来假设一个场景,小明是一个学生,他同时是班干部和学生会的干部,而学生会干部可以有多个学生,这样学生和学生会干部表就构成了多对多的关系

用户表和角色表的关系为,一个用户有多个角色,一个角色被多个用户使用
多对多查询的需求:查询用户同时查询出该用户的所有角色

要实现这种多对多的关系,我们不仅需要role角色表,也需要一个中间表,用户和角色表之间的桥梁——用户id和角色id对应的表。

select u,r,rid rid,uid uid from user u left join user_role ur on uid=uruid inner join role r on urrid=rid

select from user u,user_role ur,role r where uid = uruid and urrid =rid

User类添加

UserMapper接口添加

配置sqlMapperConfigxml,给Role增加别名

这几年来注解开发越来越流行,Mybatis也可以使用注解开发方式,这样我们就可以减少编写Mapper映射文件了。
我们先围绕一些基本的CRUD来学习,再学习复杂映射多表 *** 作。

修改MyBatisTestjava,将公共 *** 作抽取出来

删除了之后,我们没有了配置文件了呀,那怎么做呢。
我们之前在sqlMapperConfigxml里面配置了

删除了之后我们就得加载映射关系,指定接口所在的包

没有问题!说明可以运行。

实现复杂关系映射之前我们可以在映射文件中通过配置<resultMap>来实现,使用注解开发后,我们可以使用
@Results注解,@Result注解,@One注解,@Many注解
组合完成复杂关系的配置

前面我们用配置文件的方式实现了order和user的一对多查询,同样的我们也可以使用注解实现。

用户表和订单表的关系为,一个用户有多个订单,一个订单只从属于一个用户
一对一查询的需求:查询一个订单,与此同时查询出该订单所属的用户

对应的sql语句:

测试

两个都可以正常运行。
我们上面的查询方式是一次查两张表,但是我们也可以通过查order表获取uid,再通过uid去查user表,这种方法怎么实现呢?
不知道你还记不记得,前面我们使用了<association>进行order和user表的一对一查询的封装,前面图中提到了@One属性,就是它的一种替代

用户表和订单表的关系为,一个用户有多个订单,一个订单只从属于一个用户
一对多查询的需求:查询一个用户,与此同时查询出该用户具有的订单

可能这种方式用的比较多

对应的sql语句:

给OrderMapperjava增加一个查询方法

修改UserMapperjava

但是这种方法,其实是查到了所有的user,其中有些有orderList,原因在于这其实是一种按顺序的查询方式,先查了user表再查了order表

select ,oid oid from user u,orders o where uid = oid 是不一样的

再来回顾一下多对多的查询
用户表和角色表的关系为,一个用户有多个角色,一个角色被多个用户使用
多对多查询的需求:查询用户同时查询出该用户的所有角色
对应的sql语句:

这样子,就有个很怪的问题,注解查询每次都返回了全部的user,我不需要这么多的user啊,我只想要和role关联的那几个user,这会是一个好的方法吗。

你没有传参数,那就不写parameterType就行了啊,还有你说的跟xml配置没有关系啊,

<insert id="xxx">
insert into 表名 select 字段1,字段2 from 表名                        
</insert>

你要保证select出的字段与你要插入的字段那些类型什么的都要一样才可以

MyBatis的插件MyBatis-Plus,又叫苞米豆(baomidou),简称MP,官方说,它是为了猿类崛起而生,为了提高生产率而生,为了简化开发而生,不管它为了什么而生吧,反正是它出生了。

MyBatis-Plus对MyBatis只做增强不做改变,所以引入它不会对现有工程产生影响,只需要做简单的配置,就可以快速进行单表的CRUD *** 作,从而节省时间,提高效率。

MyBatis-Plus插件有很丰富的功能,比如:单表CRUD *** 作、代码生成、自动分页、逻辑删除等。

下面我们来简单介绍一下MyBatis-Plus的使用

1、pomxml

去掉MyBatis的核心依赖(orgmybatisspringbootmybatis-spring-boot-starter),增加MyBatis-Plus的依赖:

2、配置applicationyml、po、dao和Application

applicationyml中配置数据库连接:

blog数据库中article表的实体类ArticlePo:

注解说明:

@TableName:表名注解,标识实体类对应的表

@TableId注解:主键注解,当type = IdTypeAUTO时,表示这个主键是自增主键

blog数据库中article表的dao,ArticleDao:

BaseMapper接口:利用Mybatis接口编程的实现机制,默认提供了一系列的增删改查的基础方法。

在Article11Application中配置 MapperScan 注解:

3、增加数据

insert:增加数据,insert返回值int代表insert了多少条记录

示例:在ArticleController中编写增加数据的接口:

说明:

1)一般业务逻辑处理在service层,这里为了方便,直接在controller中演示了

2)@Resource注解:注入ArticleDao,后续的方法中不再重复注入

4、删除数据

delete:物理删除数据,返回删除了多少条数据

示例,删除title为Mybatis-Plus test的数据:

说明:

1)物理删除后,恢复数据很困难,所以一般情况下,业务处理采用逻辑删除的方式

5、更新数据

update: 更新数据

示例,修改title为Mybatis-Plus test的数据的title为Mybatis-Plus update:

updateById: 根据主键id更新数据

示例,修改id为7的数据的title为Mybatis-Plus updateById:

注意 :

1、updateById方法:若传入实体Model,则会根据主键把其他字段全部更新一遍

问题:使用baomidou拿出某条数据的数据实体后,有其他人把数据库中这条数据的某个字段更新了,再用baomidou的updateById方法更新时,会把此字段再更新回来

解决:

方法1:使用sql语句,只更新需要更新的字段

方法2:新建实体Model,Model中只放主键和需要更新的字段

6、查询数据

selectOne: 查询单条数据

示例,查询id为7的数据:

注意 :

1、selectOne方法

1)结果没有数据时,返回null

2)结果有一条数据时,返回此数据

3)结果有两条或两条以上数据时,报错

解决办法:在最后增加 last(" limit 1 ") 语句

selectList: 查询多条数据

示例:查询title为Mybatis-Plus update的数据

7、打印sql日志

打印执行的sql,在applicationyml中配置,一般配置在开发环境

MyBatis-Plus的其他注意事项

1、如果数据库表字段中有desc、describe等mysql关键词或预留关键词,使用selectList/selectOne会报错,需要单独写sql查询语句

2、有时我们需要在Dao中单独写方法来写sql语句,这时方法的命名跟baomidou自带的命名不要一样,否则即使参数不同,也会有问题:Dao中单独写的方法,会把baomidou的方法覆盖,就调用不到baomidou的方法了

本文示例代码, 详见
>在对一套系统进行开发前,应该预先做整体的功能需求分析,把需要开发或者修改的地方列一个清单,对照清单修改,这样能够降低功能遗漏的问题。
另外就是做好版本控制,对于修改前与修改后可以有完整的对比,而不用手动将原来的代码复制一份。
从Controller到Mapper如果只是搭建框架,用不了几分钟,一般做过几次的人,会保留一份基础框架模板,需要的时候直接拿过来用就行了,可以说基本不需要花什么时间。
你说的完全开发完,不知道以什么标准来说?如果只是全查,全删,单一添加,单个字段修改的话,全部写完也就四条SQL语句,用不了多少时间,除了使用mapperxml方式,也可以使用注解的方式写,可以减少xml标签的编写。
如果是还有其它具体要求的功能,所花费的时间因人因需求而异,不同的功能,复杂度不一样,功能个数不一样,不同的能力的人开发,所花费的时间是不一样的,这个需要根据实际情况来评估。

1resultMap
SQL 映射XML 文件是所有sql语句放置的地方。需要定义一个workspace,一般定义为对应的接口类的路径。写好SQL语句映射文件后,需要在MyBAtis配置文件mappers标签中引用,例如
<mappers>
<mapper resource="com/liming/manager/data/mappers/UserMapperxml" />
<mapper resource="com/liming/manager/data/mappers/StudentMapperxml" />
<mapper resource="com/liming/manager/data/mappers/ClassMapperxml" />
<mapper resource="com/liming/manager/data/mappers/TeacherMapperxml" />
</mappers>
当Java接口与XML文件在一个相对路径下时,可以不在myBatis配置文件的mappers中声明。
SQL 映射XML 文件一些初级的元素:
(1) cache – 配置给定模式的缓存
(2) cache-ref – 从别的模式中引用一个缓存
(3) resultMap – 这是最复杂而却强大的一个元素了,它描述如何从结果集中加载对象
(4) sql – 一个可以被其他语句复用的SQL 块
(5) insert – 映射INSERT 语句
(6) update – 映射UPDATE 语句
(7) delete – 映射DELEETE 语句
(8) select - 映射SELECT语句

默认情况下,使用 #{} 格式的语法会导致 MyBatis 创建 PreparedStatement 参数占位符并安全地设置参数(就像使用 一样)。 这样做更安全,更迅速,通常也是首选做法,不过有时你就是想直接在 SQL 语句中插入一个不转义的字符串。 比如,像 ORDER BY,你可以这样来使用:
ORDER BY ${columnName}
这里 MyBatis 不会修改或转义字符串。

当 SQL 语句中的元数据(如表名或列名)是动态生成的时候,字符串替换将会非常有用。 举个例子,如果你想通过任何一列从表中 select 数据时,不需要像下面这样写:

可以只写这样一个方法:

其中 ${column} 会被直接替换,而 #{value} 会被使用 预处理。 因此你就可以像下面这样来达到上述功能:

这个想法也同样适用于用来替换表名的情况。

提示 用这种方式接受用户的输入,并将其用于语句中的参数是不安全的,会导致潜在的 SQL 注入攻击,因此要么不允许用户输入这些字段,要么自行转义并检验。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/13350959.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-07-19
下一篇 2023-07-19

发表评论

登录后才能评论

评论列表(0条)

保存