mybatis的sql语句及使用mybatis的动态sqlmybatis防注入
mybatis的sql语句及使⽤mybatis的动态sqlmybatis防注⼊
由于看到写的⽐较详细的⽂档这⾥将之前的删掉了,只留下⼀些我认为能帮助理解的和关于动态sql及防注⼊的⼀些理解。⽂档链接 :
1
2
3 SELECT id, username, birthday, sex, address FROM `user`
4 WHERE 1=1
5
6 AND sex = #{sex}
7
8
9 AND username LIKE
10 '%${username}%'
11
12
注意字符串类型的数据需要要做不等于空字符串校验。
上⾯的sql还有where 1=1 这样的语句,很⿇烦 可以使⽤mybatis的where标签
5
6
7 SELECT id, username, birthday, sex, address FROM `user`
8
9
10
11 AND sex = #{sex}
12
13
14 AND username LIKE
15 '%${username}%'
16
17
18
效果是⼀样的
Sql中可将重复的sql提取出来,使⽤时⽤include引⽤即可,最终达到sql重⽤的⽬的。
然⽽ 然⽽ 然⽽ 引⽤结果resultMap巨tm诡异resultMap 和其中的参数重复的话会报错 所以关于resultMap⼀定要慎重填写 必要的时候把属性都填上不要偷懒
1
2
3
4
5 SELECT
6
7
8
9 AND sex = #{sex}
10
11
12 AND username LIKE
13 '%${username}%'
14
15
16
17
18
19
20 id, username, birthday, sex, address
21
再这个xml中你甚⾄可以使⽤别的xml中的sql 加上namespace
即可:这样
关于foreach 这个也很好⽤,⽅便:
这是接⼝ 注意接⼝⽅法名和maper.xml的id⼀致 否则⽆法⾃动映射。
这是mapper。xml的
需要了解⼀下foreach⾥⾯都是些什么东西 collection:你传给xml参数的类型 也是需要遍历前的对象 item给遍历出来的结果⼀个名字,可以参照foreach⽅法index 就是index的意思 open:开始遍历前加上的字符 在这⾥是 紧跟着 in 后⾯的 close:遍历结束后加上的字符 separator 每个遍历结果之间的分隔符 那么总的
就是 delete from mall_user where user_id in ( 1,2,3); mybatis会知道最后⼀个遍历结果不要加,
还⼀个mybatis放sql注⼊ 总得来说就是别⽤${} 多⽤#{}详解:mybatis实现防⽌sql注⼊总的来说是依靠其预编译过程和存储过程。存储过程就是mybatis提供⼀组完
成特定功能的SQL语句集,经编译后存储在数据库中,⽤户通过调⽤存储过程并给定参数(如果该存储过程带有参数)就可以执⾏它,也可以避免SQL注⼊攻击。
预编译:我们传给mybatis的参数可以理解为占位符,在预编译过程mybatis检查语句的正确性然后将我i们给的占位符放到它预编译的语句的占位符上
补充说⼀下关于sqlMapConfig。xml中setting配置 我不怎么⽤但还是补充介绍⼀下
mybatis--MyBatis动态SQL语句
mybatis--MyBatis动态SQL语句
mybatis 的动态sql语句是基于OGNL表达式的。可以⽅便的在 sql 语句中实现某些逻辑. 总体说来mybatis 动态SQL 语句主要有以下⼏类:
1. if 语句 (简单的条件判断)
2. choose (when,otherwize) ,相当于java 语⾔中的 switch ,与 jstl 中的choose 很类似.
3. trim (对包含的内容加上 prefix,或者 suffix 等,前缀,后缀)
4. where (主要是⽤来简化sql语句中where条件判断的,能智能的处理 and or ,不必担⼼多余导致语法错误)
5. set (主要⽤于更新时)
6. foreach (⽤于mybatis语句查询)
1.if语句(简单的条件判断)
(1)数据库my的user表数据为:
(2)⾸先创建⼀个mybatis项⽬,mybatis_008
(3)建⽴com.zk.dao包下的IUser接⼝:
IUser.java
package com.zk.dao;
import org.apache.ibatis.annotations.Param;
import er;
public interface IUser {
public User findUserWithNameLike(@Param("id")int id, @Param("name")String name);
}
(4)在com.zk.pojo包下建⽴User实现IUser接⼝中的⽅法,并配置UserMapper.xml
User.java
package com.zk.pojo;
public class User {
private int id;
private String name;
private String level;
private String phone;
public int getId() {
MyBatis动态SQL查询语句(10)
MyBatis动态SQL查询语句(10)
MyBatis 动态SQL查询语句:根据传输参数进⾏判断是否作为查询条件
1、mapper.xml⽂件
PUBLIC "-////DTD Mapper 3.0//EN"
"/dtd/mybatis-3-mapper.dtd">
select
id,name,age,sex
from
t_person_01
where
name = #{name}
and id = #{id}
2、测试类
@Test
public void queryPersonByAgeAndNameWithSQLTag() throws Exception{
Reader reader = Resources.getResourceAsReader("mybatis-03.xml");
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);
SqlSession session = sessionFactory.openSession();
Person person = new Person();
person.setName("zhangsan");
// 动态代理
PersonMapper personMapper = session.getMapper(PersonMapper.class);
List personList = personMapper.queryPersonByAgeAndNameWithSQLTag(person);
System.out.println("动态SQL查询结果为:"+personList);
session.close();
}
3、mapper j接⼝类
/**
* @author :jack.zhao
MyBatis中动态sql实现传递多个参数并使用if进行参数的判断和实现like模糊搜索以。。。
MyBatis中动态sql实现传递多个参数并使⽤if进⾏参数的判断和
实现like模糊搜索以。。。
场景
在mapper接⼝层⽅法参数有id的数组和姓名的模糊搜索和类型的三个参数。
现在需要将这三个参数传递在动态sql的xml中接受并进⾏判断不为空。
然后查询数据库中记录在第⼀个参数id数组中的并且姓名是模糊搜索的并且类型是直接相等于的。
注:
实现
mapper层接⼝写法:
public List selectKqKqryszListBySx(@Param("array")Long[] bmids, String xm, int lx);
xml写法:
SELECT j.id,
j.xm,
j.bm,
k.tszt,
z.zwgz,
s.dict_label AS dklx,
k.bcz,
k.bc,
k.zbbc,
k.ddid,
k.qysjdk
from dp_jbxx j LEFT JOIN kq_kqrysz k on j.gh = k.gh
LEFT JOIN dp_zcxx z ON j.gh = z.gh
LEFT JOIN kq_dksz d ON j.gh = d.gh
LEFT JOIN dp_grxx g ON j.gh = g.gh
LEFT JOIN sys_dict_data s on d.dkzt = s.dict_value
AND
s.dict_type="kq_kqgl_dksz_zt"
${item}
and j.xm like concat('%', #{xm}, '%')
and g.ryfl = #{lx}
注意:
上⾯是⼀些相关的关联查询。
下⾯的
and j.bmid in
${item}
就是实现查询id在参数ids这个数组中的。
注意这⾥的array要与接⼝⽅法中@Param("array")⼀致。
然后这⾥传递的参数名字if test发判断中直接使⽤对应接⼝⽅法中的参数名,不⽤使⽤#{xm}这种的⽅式,但是在⾥⾯的sql语句中要使⽤这种
MyBatis在注解上使用动态SQL(@select使用if)
MyBatis在注解上使⽤动态SQL(@select使⽤if)
1、⽤script标签包围,然后像xml语法⼀样书写
@Select({""})
2、⽤Provider去实现SQL拼接,例如:
public class OrderProvider {
private final String TBL_ORDER = "tbl_order";
public String queryOrderByParam(OrderPara param) {
SQL sql = new SQL().SELECT("*").FROM(TBL_ORDER);
String room = param.getRoom();
if (StringUtils.hasText(room)) {
sql.WHERE("room LIKE #{room}");
}
Date myDate = param.getMyDate();
if (myDate != null) {
sql.WHERE("mydate LIKE #{mydate}");
}
return sql.toString();
}
}
public interface OrderDAO {
@SelectProvider(type = OrderProvider.class, method = "queryOrderByParam")
List queryOrderByParam(OrderParam param);
}
注意:⽅式1有个隐患就是当传⼊参数为空的时候,可能会造成全表查询。
复杂SQL⽤⽅式2会⽐较灵活(当然,并不建议写复杂SQL),⽽且可以抽象成通⽤的基类,使每个DAO都可以通过这个基类实现基本的通
⽤查询,原理类似Spring JDBC Template。
3、说明:
如果XML元素嵌⼊在")
但是使⽤元素会触发SQL Mapper配置解析异常,由以下原因引起:
org.apache.ibatis.builder.BuilderException: Unknown element in SQL statement. at org.apache.ibatis.scripting.xmltags.XMLScriptBuilder.parseDynamicTags
MyBatis学习 之三动态SQL语句
MyBatis学习 之三动态SQL语句
三、动态SQL语句
MyBatis学习 之 一、MyBatis简介与配置MyBatis+Spring+MySql
MyBatis学习 之 二、SQL语句映射文件(1)resultMap
MyBatis学习 之 二、SQL语句映射文件(2)增删改查、参数、缓存
MyBatis学习 之 三、动态SQL语句
MyBatis学习 之 四、MyBatis配置文件
有些时候,sql语句where条件中,需要一些安全判断,例如按某一条件查询时如果传入的参数是空,此时查询出的结果很可能是空的,也许我们需要参数为空时,是查出全部的信息。使用Oracle的序列、mysql的函数生成Id。这时我们可以使用动态sql。
下文均采用mysql语法和函数(例如字符串链接函数CONCAT)。
3.1 selectKey 标签
在insert语句中,在Oracle经常使用序列、在MySQL中使用函数来自动生成插入表的主键,而且需要方法能返回这个生成主键。使用myBatis的selectKey标签可以实现这个效果。
下面例子,使用mysql数据库自定义函数nextval('student'),用来生成一个key,并把他设置到传入的实体类中的studentId属性上。所以在执行完此方法后,边可以通过这个实体类获取生成的key。
parameterType="liming.student.manager.data.model.StudentEntity" keyProperty="studentId">
select
nextval('student') INSERT INTO STUDENT_TBL(STUDENT_ID,
STUDENT_NAME, STUDENT_SEX, STUDENT_BIRTHDAY, STUDENT_PHOTO,
CLASS_ID, PLACE_ID) VALUES (#{studentId}, #{studentName}, #{studentSex},
8.mybatis动态SQL模糊查询(多参数查询,使用parameterType)
8.mybatis动态SQL模糊查询(多参数查询,使⽤
parameterType)
多参数查询,使⽤parameterType。实例:
⽤户User[id, name, age]
1.mysql建表并插⼊数据
2.Java实体类
public class User {
public User() {
}
public User(int id, String name, int age) {
super();
this.id = id;
= name;
this.age = age;
}
private int id;
private String name;
private int age;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
= name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + ", age=" + age + "]";
}
}
3.创建查询参数实体类
/**
* 模糊查询User的类
* @author Administrator
*
*/
public class SelectUserCondition {
private String name;//姓名
private int minAge;//最⼩年龄
private int maxAge;//最⼤年龄
mybatis group by if用法
mybatis group by if用法
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。在
MyBatis 中,group by 子句经常用于对数据进行分组,而 if 语句则用于动态生成 SQL。下面我将详细介绍 MyBatis 中如何使用 group by 与 if 结合来动态生成 SQL。
使用 元素动态添加 group by 子句
在 MyBatis 的 XML 映射文件中,你可以使用 元素来根据条件动态添加 group
by 子句。例如,假设你有一个查询需要根据用户的输入动态地按某个字段进行分组,你可以这样做:
xml
SELECT column1, column2, SUM(column3)
FROM your_table
GROUP BY ${groupByColumn}
在这个例子中,groupByColumn 是传入查询的一个参数。如果 groupByColumn 不为空,MyBatis 将会添加 GROUP BY 子句并按照 groupByColumn 的值进行分组。
注意安全性
使用 ${} 插入字段名或表名时要特别小心,因为这可能会导致 SQL 注入。确保传入的字段名或表名是安全的,或者通过某种方式进行了验证和清理。
结合 , ,
你还可以使用 , , 和 元素来创建更复杂的条件逻辑,以决定是否需要添加 group by 子句,以及按哪个字段进行分组。
总的来说,MyBatis 提供了强大的动态 SQL 生成功能,使得你可以根据应用的需求灵
活地构建 SQL 查询。
mybatis instr用法
mybatis instr用法
MyBatis是一种Java持久化框架,它提供了一个简单而强大的自定义SQL映射功能。作为一个开发者,熟悉MyBatis的各种特性和用法对于高效地工作和提升开发效率非常重要。其中一个特性是``标签,也称为MyBatis的`INSTR`用法,可以在SQL查询中方便地使用循环进行参数值的迭代。本文将一步一步地解释MyBatis中`INSTR`的使用,包括语法、示例和最佳实践。
第一部分:了解`INSTR`标签的语法和语义
- `INSTR`标签用于在SQL查询中生成一个包含循环的参数值列表。
- 它可以用于任何SQL查询,包括SELECT、INSERT、UPDATE和DELETE语句。
- `INSTR`标签有以下属性可用于配置循环的参数值列表:
- collection:指定一个集合,用于迭代参数值。
- item:指定在每次迭代中要使用的变量名。
- open:指定循环的起始字符(可选,默认值为`(`)。
- close:指定循环的结束字符(可选,默认值为`)`)。
- separator:指定每个参数值之间的分隔符(可选,默认值为`,`)。
第二部分:使用`INSTR`标签进行循环迭代示例
为了更好地理解如何使用`INSTR`标签,在这一部分将提供一个示例。
假设我们有一个表`users`,其中存储了用户的信息,包括`id`、`name`和`age`。我们想要根据一组用户ID来查询他们的详细信息。现在,我们可以使用`INSTR`标签来实现这个功能。
示例代码如下:
SELECT * FROM users
WHERE id IN
separator=",">
#{id}
在这个示例代码中,我们首先定义了一个名为`getUserDetails`的查询语句,并指定了返回结果的类型为`User`。然后,我们使用`INSTR`标签来定义一个循环,将`userIds`集合中的每个值作为查询条件的一部分。在循环中,我们使用`#{id}`来表示当前迭代的参数值。
mybatis main方法
mybatis main方法
MyBatis Main方法使用指南
介绍
在MyBatis中,main方法是一个非常常用的方法,它用于启动一个MyBatis应用程序并执行相关的操作。本文将详细介绍MyBatis
main方法的各种用法和注意事项。
使用方法
• 导入MyBatis的相关依赖 MyBatis需要依赖于一些Jar包,你需要在你的项目中导入这些Jar包。例如,在Maven项目中,你可以在文件中添加如下依赖:
mybatis
• 编写MyBatis的配置文件 在MyBatis中,配置文件用于定义数据库连接信息以及ORM映射等相关配置。你需要创建一个文件,并在其中配置相关信息。例如:
PUBLIC "-////DTD Config //EN"
"
• 编写Mapper接口和映射文件 在MyBatis中,Mapper接口用于定义与数据库交互的方法,映射文件用于定义SQL语句和结果映射关系。你需要创建一个Mapper接口和对应的映射文件。例如:
– Mapper接口:
public interface UserMapper {
User getUserById(int id);
}
– 映射文件():
"
SELECT * FROM users WHERE id = #{id}
• 编写Main方法 现在,你可以编写一个Main方法来启动MyBatis应用程序并执行相关的操作。例如: public class Main {
MyBatis经典面试题及答案
MyBatis经典⾯试题及答案
1、什么是MyBatis?
答:MyBatis是⼀个可以⾃定义SQL、存储过程和⾼级映射的持久层框架。
2、讲下MyBatis的缓存
答:MyBatis的缓存分为⼀级缓存和⼆级缓存,⼀级缓存放在session⾥⾯,默认就有,⼆级缓存放在它的命名空间⾥,默认是不打开的,使⽤⼆级缓存属性类需要实现Serializable序列化接⼝(可⽤来保存对象的状态),可在它的映射⽂件中配置1、⼀级缓存的⽣命周期有多长?
a、MyBatis在开启⼀个数据库会话时,会 创建⼀个新的SqlSession对象,SqlSession对象中会有⼀个新的Executor对象。Executor对象中持有⼀个新的PerpetualCache对象;当会话结束时,SqlSession对象及其内部的Executor对象还有PerpetualCache对象也⼀并释放掉。b、如果SqlSession调⽤了close()⽅法,会释放掉⼀级缓存PerpetualCache对象,⼀级缓存将不可⽤。
c、如果SqlSession调⽤了clearCache(),会清空PerpetualCache对象中的数据,但是该对象仍可使⽤。
d、SqlSession中执⾏了任何⼀个update操作(update()、delete()、insert()) ,都会清空PerpetualCache对象的数据,但是该对象可以继续使⽤ 2、怎么判断某两次查询是完全相同的查询?
mybatis认为,对于两次查询,如果以下条件都完全⼀样,那么就认为它们是完全相同的两次查询。
2.1 传⼊的statementId
2.2 查询时要求的结果集中的结果范围
2.3. 这次查询所产⽣的最终要传递给JDBC java.sql.Preparedstatement的Sql语句字符串(boundSql.getSql() )
2.4 传递给java.sql.Statement要设置的参数值
