Mybatis中SQL语句的编写
上⽂中,我们编写了⼀个最简单的sql查询语句。根据学⽣id查询对象
注意:如果输⼊参数:
是简单类型(8个基本类型加String),是可以使⽤任何占位符
占位符,#{xxxxxx}
有意义的占位符,不要随便⽤任意占位符
不过为了可读性
可读性,⼀般还是⽤有意义
对象类型,则必须是对象的属性 #{属性名}
#{属性名}
如果是对象类型
全类名)如果输出参数:如果返回值类型是⼀个对象(Student),则⽆论是返回⼀个还是多个
⼀个还是多个,在resultType中都写成entity.Student(即全类名
⼿⼯commit( );
如果使⽤的事务⽅式是 jdbc,则需要⼿⼯commit( );
同时注意到这⾥使⽤的是“#”,那么是不是只能⽤这⼀个呢。其实不然,还可以使⽤“$”。那么⼆者之间有什么区别呢?
针对简单类型(8个基本类型加String),
#{任意值}
只能⽤value,不能是其他任何值
${value}
${value},这⾥只能
另外:
#{}会⾃动给String类型加上 ‘ ’(⾃动类型转化)
${}进⾏原样输出,⽐较适⽤于动态排序(动态字段)
防⽌SQL注⼊,${}则不可以
#{}可以防⽌SQL注⼊
现在通过实例来学习SQL语句的编写(两种形式都进⾏学习)
SELECT语句
xml配置⽂件形式
xm l配置⽂件形式
注意到select标签有⼀些属性远不⽌上图三个属性,从官⽹中学习了解⼀下Select标签属性含义
由官⽹可知:
其中属性:
唯⼀的标识符,即你给这条sql语句取的唯⼀标识符,可以被⽤来引⽤这条语句。
id id:在命名空间中唯⼀的标识符
parameterType:将会传⼊这条语句的参数类的完全限定名或别名
批量更新sql语句完全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过类型处理器
parameterType
完全限定名或者是别名,其他名称mybatis不认(TypeHandler) 推断出具体传⼊语句的参数,默认值为未设置 。即传⼊参数的类型。注意是完全限定名或者是别名,
识。
弃⽤,甚⾄会被移除,不做研究
parameterMap:被弃⽤
parameterMap
集合包含的类
完全限定名或别名。 注意如果返回的是集合,那应该设置为集合包含的类 resultType:从这条语句中返回的期望类型的类的完全限定名或别名
resultType
完全限定名或别名,如上⽂说
不能同时使⽤。 即返回参数类型,同样是完全限定名或别名不是集合本⾝。可以使⽤ resultType 或者 resultMap,但不能同时使⽤
型,⽽不是
过,不论返回的是⼀个Student对象还是多个,返回类型都是Student的全类名(entity.Student)或者别名。
resultMap:外部 resultMap 的命名引⽤。结果集的映射是 MyBatis 最强⼤的特性,如果你对其理解透彻,许多复杂映射的情形 resultMap
都能迎刃⽽解。可以使⽤ resultMap 或 resultType,但不能同时使⽤。后⽂会详细介绍该属性。
清空,默认值false
默认值false。
⼆级缓存被清空
本地缓存和⼆级缓存
flushCache
flushCache:将其设置为 true 后,只要语句被调⽤,都会导致本地缓存
timeout:这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为未设置(依赖驱动)。
timeout
设置值相等。 默认值为未设置(依赖驱
结果⾏数和这个设置值相等
批量返回的结果⾏数
fetchSize
fetchSize:这是⼀个给驱动的提⽰,尝试让驱动程序每次批量返回
动)。
statement:TypeSTATEMENT,PREPARED 或 CALLABLE 中的⼀个。这会让 MyBatis 分别使⽤
statement
Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED。
resultSetType:FORWARD_ONLY,SCROLL_SENSITIVE, SCROLL_INSENSITIVE 或 DEFAULT(等价于 unset) 中的⼀ resultSetType
TYPE_SCROLL_INSENSITIVE:双向滚动,但不及个,默认值为 unset (依赖驱动)。 TYPE_FORWORD_ONLY
TYPE_FORWORD_ONLY:只可向前滚动;TYPE_SCROLL_INSENSITIVE
TYPE_SCROLL_SENSITIVE:双向滚动,并及时跟踪数据库的更新,时更新,就是如果数据库⾥的数据修改过,并不在ResultSet中反应出。TYPE_SCROLL_SENSITIVE
以便更改ResultSet中的数据。
databaseId:如果配置了数据库⼚商标识(databaseIdProvider),MyBatis 会加载所有的不带 databaseId 或匹配当前
databaseId
databaseId 的语句;如果带或者不带的语句都有,则不带的会被忽略。(不懂,放在之后考虑)
嵌套结果 select 语句适⽤:如果为 true,就是假设包含了嵌套结果集或是分组,这样的话当返 resultOrdered
resultOrdered:这个设置仅针对嵌套结果
回⼀个主结果⾏的时候,就不会发⽣有对前⾯结果集的引⽤的情况。 这就使得在获取嵌套的结果集的时候不⾄于导致内存不够⽤。默认值:false。
逗号分隔
resultSets
resultSets:这个设置仅对多结果集的情况适⽤。它将列出语句执⾏后返回的结果集并给每个结果集⼀个名称,名称是逗号
的。
好,看了这么多,主要使⽤的约莫是 id ,parameterType,resultType, resultMap这四项。于是本节刚开始的语句就是⼀个id
完全限定名 ,那么就是别名了为queryStudentByStuno,传⼊参数类型为int,返回类型为student的⼀条sql语句。显然student,int不是完全限定名
哦。
现在简单介绍⼀下别名怎么实现。
在conf配置⽂件中设置别名
注解形式
@Select注解完成sql语句编写,那么select标签那么多属性怎么设置呢
前⽂中已经知道⽤@Select
Options注解
@Options注解。很多属性可以通过该注解完成配置
由上图可知,在@Select注解上⼜有⼀个@Options
insert,update ,delete 语句
xm l配置⽂件形式
xml配置⽂件形式
这时候我们就可以直接看这三个标签有什么属性了。⼤同⼩异,仅有⼏个不同。如下:
insert 和 update 有⽤)这会令 MyBatis 使⽤ JDBC 的 getGeneratedKeys ⽅法来取出 useGeneratedKeys:(仅对 insert 和 update
useGeneratedKeys:
数据库内部⽣成的主键(⽐如:像 MySQL 和 SQL Server 这样的关系数据库管理系统的⾃动递增字段),默认值:false。
由数据库内部⽣成的主键
唯⼀标记⼀个属性,MyBatis 会通过 getGeneratedKeys 的返回值或者通
insert 和 update 有⽤)唯⼀标记⼀个属性
keyProperty:
keyProperty:(仅对 insert 和 update 有⽤
过 insert 语句的 selectKey ⼦元素设置它的键值,默认值:未设置(unset)。如果希望得到多个⽣成的列,也可以是逗号分隔的属性名称列表。
insert 和 update 有⽤)通过⽣成的键值设置表中的列名,这个设置仅在某些数据库(像
keyColumn:
keyColumn:(仅对 insert 和 update 有⽤
主键列不是表中的第⼀列的时候需要设置。如果希望使⽤多个⽣成的列,也可以设置为逗号分隔的属性名称列PostgreSQL)是必须的,当主键列不是表中的第⼀列的时候需要设置
表。
order:
BEFORE,那么它会⾸先⽣成主键,设置 keyProperty 然后执⾏插 order:这可以被设置为 BEFORE 或 AFTER。如果设置为 BEFORE
AFTER,那么先执⾏插⼊语句,然后是 selectKey 中的语句 - 这和 Oracle 数据库的⾏为相似,在插⼊语句内部可能有嵌⼊语句。如果设置为 AFTER
⼊索引调⽤。
其实也没怎么看懂,⼤部分就默认设置不去动它就⾏。后续要是有所⽤到再来研究。
代码如下:
注解形式代码如下:
在编写insert语句时,出现了⼀个bug bug。语句如下:
@Insert("insert into student(stuno,stuname,stuage,gradename) values(#{stuno},#{stuname},#{stuage
},#{gradename})")public void insert(int int stuNo,String stuName,int int stuAge,String gradeName);
然后执⾏插⼊时发现报错
查询得到两种⽅案:
第⼀种在参数前⾯加@Param("")
@Insert("insert into student(stuno,stuname,stuage,gradename) values(#{stuNo},#{stuName},#{stuAge},#{gradeName})")public void insert(@Param("stuNo") int int No,@Param("stuName") String
Name,@Param("stuAge") int int Age,@Param("gradeName")String grade);
⼀定要关注@Param("")引号⾥⾯的名字⼀定要同values(#{))中{}中的名称⼀⼀对应,⼀模⼀样⼀⼀对应,⼀模⼀样。
第⼆种⽅法根据提⽰把参数名换成
第⼆种⽅法根据提⽰把参数名换成arg3, arg2, arg1, arg0, param3, param4, param1, param2即可@Insert("insert into student(stuno,stuname,stuage,gradename) values(#{arg0},#{arg1},#{arg2},#{arg3})")
public void insert(int int stuNo,String stuName,int int stuAge,String gradeName);
经测试,还必须必须要按照arg0-3或者是param1-4顺序不能出现超过这个数字如arg5,不然同样报错,类似下图
递多个参数所引起的,后续会细致探讨。
以上报错是由传递多个参数
这样考虑到更新操作同样是传⼊多个参数,所以选择直接传递⼀个学⽣类对象进去,这样就变成了传递⼀个参数了。代码如下:
@Update("update student set stuname=#{stuName},stuage=#{stuAge},gradename=#{gradeName} where stuno =#{stuNo}") public void updateById(Student stu);
学⽣对象即可
测试时候传递⼀个学⽣对象
测试,更新成功。
其余知识,下篇介绍。
才疏学浅之处,切莫在意。
——2019.5.30 下午
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论