JAVAEE框架技术之8-myBatis ORM框架技术参数和动态SQL语句
Posted teayear
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVAEE框架技术之8-myBatis ORM框架技术参数和动态SQL语句相关的知识,希望对你有一定的参考价值。
parameterType
传入多个参数
确切点是方法的输入参数,一般都是采用直接使用pojo类。此时在mapper.xml文件中的SQL语句不用再写parameterType属性,而是用arg0,arg1,arg2,arg3…或者param1,param2,param3…代替。
引出问题
/**
* 登录
* @param name
* @param passworld
*/
public User login(String name ,String password);
<!--登录-->
<select id="login" resultType="User">
select * from tb_user where user_name = #username and password = #password
</select>
@Test
public void testLogin()
User u = userMapper.login("jack","123");
System.out.println(u);
如果传入两个参数或者更多的参数,会发现,多个参数是找不到了,错误如下:
解决方式1
在mapper.xml中使用 0,1这样的序号去,0表示第一个参数,1表示第二个参数。(从0开始数)
<!--登录-->
<select id="login" resultType="User">
select * from tb_user where user_name = #arg0 and password = #arg1
</select>
或者 用param1 param2 这个时就是从1开始
<!--登录-->
<select id="login" resultType="User">
select * from tb_user where user_name = #param1 and password = #param2
</select>
解决方式2
通过@Param来指定参数名,你写什么就接受什么
#与$区别
1、$字符串拼接,#参数站位相当于?
2、$不能够防止sql注入,#可以防止sql注入的
3、$要考虑参类型 ,#不用考虑参数类型
4、$可以替换sql语句任何一个内容,#只能替换参数
#的用法
######不用考虑参数类型
######可以防止sql注入
<!--登录-->
<select id="login" resultType="User">
<!--使用#-->
select * from tb_user where user_name = #name and passworld = #password
</select>
/**
* 登录
*/
public User login(@Param("name") String name ,@Param("passworld") String passworld);
@Test
public void testLogin()
User u = userMapper.login("jack", "123");//#不用考虑参数类型
User u = userMapper.login("' or '1' = '1", "' or '1' = '1");//#防止sql注入
System.out.println(u);
- 根据姓名进行模糊查询
/**
* 根据姓名进行模糊查询
* @param name
* @return
*/
public List<User> queryByLikeName(String name);
<!--根据姓名进行模糊查询-->
<select id="queryByLikeName" resultType="User">
select * from tb_user where user_name like concat('%',#name,'%')
</select>
@Test
public void teseQueryByLikeName()
List<User> list = this.userMapper.queryByLikeName("ja");
for(User user : list)
System.out.println(user);
$的用法
用于字符串拼接
/**
* 根据表名来查询
* @param name
*/
public List<User> queryByTableName(String name);
<!--根据表名来查询-->
<select id="queryByTableName" resultType="User">
select * from $name
</select>
@Test
public void testqueryByTableName()
List<User> list = this.userMapper.queryByTableName("tb_user");
for(User user : list)
System.out.println(user);
$ 需要考虑参数类型
$不防止sql注入
<!--登录-->
<select id="login" resultType="User">
<!--使用$ 需要考虑参数类型-->
select * from tb_user where user_name = '$name' and passworld = '$passworld'
</select>
/**
* 登录
*/
public User login(@Param("name") String name ,@Param("passworld") String passworld);
@Test
public void testLogin()
User u = userMapper.login("jack", "123");//$不用考虑参数类型
User u = userMapper.login("' or '1' = '1", "' or '1' = '1");//$防止sql注入
System.out.println(u);
#和$的区别
$可以代替所有#
如果传入的数据,不是sql中的字段的时候,就不能够使用#.
通常使用#。
选择获取参数的时候,首要选择的# 的方式
(1、可以防止sql注入,2、可以不用考虑数据类型,简化书写,3、sql是参数的话的sql,预编译的sql,速度会块一些)
当#用不了的时候,去选择$例如 ,sql需要改变是表名的情况,就可使用$的方式。
总结:能用# 就不选择$
ResultMap 用法
ResultMap 是Mybatis中最为重要的元素,使用ResultMap 可以解决两大问题:
1、pojo属性名与数据库字段名不一致问题
2、完成高级查询,一对一,一对多, 多对多(后面讲)
代码实现
<!--查询所有映射-->
<!--
id:resultMap的标识
type:映射的类型
autoMapping:true(默认) 支持 属性名与字段名自动映射 false:只针对resultMap定义的属性映射
-->
<resultMap id="userResultMap" type="User" autoMapping="true">
<!--id一般作为主键,它有自己的标签,实现属性名与字段名一一映射-->
<id column="id" property="id"/>
<!--除了id以外的字段,用result标签实现属性名与字段名一一映射-->
<result column="user_name" property="userName"/>
<!--如果,属性名与字段一致,可以省略不写-->
<result column="sex" property="sex"/>
</resultMap>
<!--查询所有-->
<select id="queryAllUser" resultMap="userResultMap">
select * from tb_user
</select>
sql片段
作用:把重复的sql语句抽出来来放到sql标签中,然后通来引入
用法1
<!--抽取sql-->
<sql id="userColumn">
id ,user_name ,passworld , sex
</sql>
<!--查询所有-->
<select id="queryAllUser" resultMap="userResultMap">
select <include refid="userColumn"/> from tb_user
</select>
如出现以下问题,请参考解决即可:
去掉xml:iBatis3:sql|select|insert|update|delete|statement里面的sql校验即可
用法2
以下用法1抽取的sql只能在本xml中使用,那如何这个抽取的sql其他xml也想使用怎么办呢?用法2就是可以将sql单独抽取到一个文件中,这样其他的xml就可以直接使用
<mapper namespace="abc">
<!--抽取sql-->
<sql id="userColumn">
id ,user_name ,passworld , sex
</sql>
</mapper>
<!--查询所有-->
<select id="queryAllUser" resultMap="userResultMap">
select <include refid="abc.userColumn"/> from tb_user
</select>
<!--注意别忘了:mybatis-config.xml 引入-->
<mapper resource="UserSQLMapper.xml"/>
动态sql
业务场景:在我们生活中很多业务常常遇到动态搜索的情况,比如搜索民宿,根据位置,价格,面积等等情况动态搜索,参数等信息可以根据我们需求改变,这里就涉及到了我们Mybatis常说的动态SQL。
Mybatis 动态SQL,通过 if, choose, when, otherwise, trim, where, set, foreach等标签,可组合成非常灵活的SQL语句,从而在提高 SQL 语句的准确性的同时,也大大提高了开发人员的效率。
Mybatis提供了动态SQL,也就是可以根据用户提供的参数,动态决定查询语句依赖的查询条件或SQL语句的内容。
标签名 | 解释 |
---|---|
if | 单条件分支判断 |
choose, when, otherwise | 多条件分支判断 |
where | 处理sql条件接拼where |
set | 处理sql条件接拼set |
foreach | 循环操作 |
trim | 处理sql条件拼接 |
动态sql-if标签
需求1:查询男性用户,如果输入了姓名,姓名进行模糊查找,如果不输入就按男性用户来查询
/**
查询男性用户,如果输入了姓名,姓名进行模糊查找,如果不输入就按男性用户来查询
*/
public List<User> queryLikeByName(String name);
<!--查询男性用户,如果输入了姓名,姓名进行模糊查找,如果不输入就按男性用户来查询-->
<select id="queryLikeByName" resultType="User">
select * from tb_user where sex = '男'
<if test="name != null and name !=''">
and user_name like concat('%',#name,'%')
</if>
</select>
//查询男性用户,如果输入了姓名,姓名进行模糊查找,如果不输入就按男性用户来查询
@Test
public void queryLikeByName()
List<User> list = this.userMapper.queryLikeByName("ck");
for(User user : list)
System.out.println(user);
动态sql-choose, when, otherwise标签
choose,when,otherwise 相当于java中的 if, else if的逻辑
如果其中的一个when 成立,则后的都不执行,如果所有when的都不成立,那么就执行otherwise
也就是谁在前面谁优先
需求2:查询男性用户,如果输入了姓名则按照姓名模糊查找,否则如果输入了年龄则按照年龄查找
/**
* 查询男性用户,如果输入了姓名则按照姓名模糊查找,否则如果输入了年龄则按照年龄查找
*/
public List<User> queryByLikeNameAndAge(@Param("name") String name , @Param("age") Integer age);
<!--查询男性用户,如果输入了姓名则按照姓名模糊查找,否则如果输入了年龄则按照年龄查找-->
<select id="queryByLikeNameAndAge" resultType="User">
select * from tb_user where sex = '男'
<choose>
<when test="name != null and name !=''">
and user_name like concat('%',#name,'%')
</when>
<when test="age != null and age !=''">
and age like concat('%',#age,'%')
</when>
<otherwise>
and id = 12
</otherwise>
</choose>
</select>
//查询男性用户,如果输入了姓名则按照姓名模糊查找,否则如果输入了年龄则按照年龄查找
@Test
public void queryByLikeNameAndAge()
List<User> list = this.userMapper.queryByLikeNameAndAge("jack", null);
for(User user : list)
System.out.println(user);
动态sql-where标签
where标签代替 sql中的where关键字
需求3:查询所有用户,如果输入了姓名按照姓名进行模糊查询,如果输入年龄,按照年龄进行查询
/**
* 查询所有用户,如果输入了姓名按照姓名进行模糊查询,如果输入年龄,按照年龄进行查询
*/
public List<User> queryByAllUserLikeNameAndAge(@Param("name") String name , @Param("age") Integer age);
<!--查询所有用户,如果输入了姓名按照姓名进行模糊查询,如果输入年龄,按照年龄进行查询-->
<select id="queryByAllUserLikeNameAndAge" resultType="User">
select * from tb_user
<where>
<if test="name != null and name!=''">
user_name like concat('%',#name,'%')
</if>
<if test="age != null and age!=''">
and age like concat('%',#age,'%')
</if>
</where>
</select>
//查询所有用户,如果输入了姓名按照姓名进行模糊查询,如果输入年龄,按照年龄进行查询
@Test
public void queryByAllUserLikeNameAndAge()
List<User> list = this.userMapper.queryByAllUserLikeNameAndAge("c", 2);
for(User user : list)
System.out.println(user);
动态sql-set标签
set标签代替 sql中set关键字
需求4:如果名字信息不是null,则修改名字, 如果age信息不是null,同时也修改age
/**
* 如果名字信息不是null,则修改名字, 如果age信息不是null,同时也修改age
*/
public Integer updateByNameOrAge(@Param("name") String name , @Param("age") Integer age , @Param("id") Integer id);
<!--如果名字信息不是null,则修改名字, 如果age信息不是null,同时也修改age-->
<update id="updateByNameOrAge">
update tb_user
<set>
<if test="name != null and name!=''">
user_name = #name,
</if>
<if test="age != null and age!=''">
age = #age
</if>
</set>
where id = #id
</update>
//如果名字信息不是null,则修改名字, 如果age信息不是null,同时也修改age
@Test
public void updateByNameOrAge()
Integer integer = this.userMapper.updateByNameOrAge("一燕", 26, 2);
sqlSession.commit();
System.out.println(integer);
动态sql-foreach标签
需求5:按照多个id查询用户信息 Select * from t_user where id in(1,2,3)
/**
* 按照多个id查询用户信息
* @param ids
* @return
*/
public List<User> queryIds(@Param("ids") int[] ids);
<!--按照多个id查询用户信息-->
<!--
collection:接受的是一个集合
item: 表示遍历的就量
open: 字符串拼接的开头
close: 字符串拼接的结尾
separator: 每一个变量拼接的分隔符
-->
<select id="queryIds" resultType="User">
select * from tb_user where id in
<foreach collection="ids" item="id" open="(" close=")" separator=",">
#id
</foreach>
</select>
// 按照多个id查询用户信息
@Test
public void queryIds()
int[] arr =1,2;
List<User> list = this.userMapper.queryIds(arr);
for(User user : list)
System.out.println(user);
动态sql-trim标签
trim元素的主要功能是可以在自己包含的内容前加上某些前缀,也可以在其后加上某写后缀,与之对应的属性是prefix和suffix;
可以把包含内容的首部某些内容覆盖,即忽略,也可以把尾部的某些内容覆盖,对应的属性是prefixOverrides和suffixOver
- 案例一 prefix用法
/**
* 查询所有,如果输入姓名,按姓名查询,如果输入性别,就按性别来查询
*/
public List<User> queryNameAndSexTrim(@Param("name") String name , @Param("sex") String sex);
<!--查询所有,如果输入姓名,按姓名查询,如果输入性别,就按性别来查询-->
<select id="queryNameAndSexTrim" resultType="User">
select * from tb_user
/*加前缀,去掉第一个前缀*/
以上是关于JAVAEE框架技术之8-myBatis ORM框架技术参数和动态SQL语句的主要内容,如果未能解决你的问题,请参考以下文章
JAVAEE框架技术之8-myBatis ORM框架技术参数和动态SQL语句
JAVAEE框架技术之7-myBatis ORM框架入门基础CRUD
JAVAEE框架技术之7-myBatis ORM框架入门基础CRUD