Mybatis动态SQL 多参数输入 非预编译传入参数

本文介绍了在Mybatis中处理动态SQL时的多参数输入,通过`@param`注解的方式实现,并探讨了`statementType="STATEMENT"`与`${}`方式的使用场景。强调了非预编译(Statement类型)可能导致的SQL注入问题,建议尽量使用预编译(PreparedStatement)以提高性能和安全性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

最近项目里想要进行大表横向分表。
对于切分的表需要有一个查询的方案。
这种方案类似于将log文件定期切分存入表进行管理。
但是动态的建表我还未研究,本次先记录动态的选择表进行查询相关的知识点

总共有2点:

  • 多参数输入
  • statementType=“STATEMENT” 和 ${} 方式

示例代码

下方mapper相关的示例代码就是包含了两个知识点。

XXXmapper.xml

  <select id="findUserByIdFromTable"
    	resultType="TestUser"
    	statementType="STATEMENT"
    	>
    	SELECT
			*
		FROM
		 	${table_name} tu
		WHERE
			tu.user_id = ${user_id}
    </select>  

XXXmapper.java

	//测试动态查询
	public List< TestUser >findUserByIdFromTable (@Param("table_name")String table_name ,@Param("user_id") Integer user_id) throws Exception;

test.java

    //通用测试函数组1
    public static void test() throws Exception {
    	//testSearchById2();
    	
        InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
        SqlSession sqlSession= sqlSessionFactory.openSession();
        TestMapper mapper =  sqlSession.getMapper(TestMapper.class);
        //4.调用Mapper对象的API
        //List<OrderEx> orders= mapper.findOrdersAndUserRstType();        
        //List<OrderEx> orders= mapper.findOrdersAndUserRstMap();
        //List<UserEx> userEx= mapper.findUsersAndOrderRstMap();

        List<TestUser> users= mapper.findUserByIdFromTable("test_user",1);
        
        System.out.println(users);
        
        //5. 打印结果
        System.out.println("test over");
        //6. 释放资源
        sqlSession.close();
        in.close();
    }

多参数输入:@param注解

多参数输入有多种方案,常用的一种办法为将需要输入的多个参数封装成一个类,封装完毕后,将整个对象作为一个参数输入。

另一个方案为本次介绍的注解方案,也很常用。

使用方法为:

@param注解添加name属性,属性的值作为键值在xml文件中以{name}的方式使用。那么以这种注解修饰的参数就会填入目标的位置,而在{name}前是选择 #还是$则根据需求来定。

(举例略,见上方的例子)

statementType=“STATEMENT” 和 ${} 方式

重点

  • 当配置statementType="STATEMENT"(非预编译)参数只能使用${}方式而不能使用#{}方式。
  • ${}方式输入参数需要注意防止SQL注入(输入的参数作为拼合SQL时破坏原本结构,导致未知后果)

PreparedStatement

Mybatis 默认情况下,将对所有的 sql 进行预编译处理。Mybatis中使用 statementType来设置编译类型,默认是PreparedStatement(预编译)。

由于预编译时数据库会进行词法和语义的解析、生成执行计划,因此占位符只能占位SQL语句中的普通值,而表名、列名、关键字等影响编译的部分是不可以使用占位符的(也就是不能使用#{}传参,而是需要使用${}传参)。

因此上方举例代码可以改为如下也不影响功能:

     <select id="findUserByIdFromTable"
    	resultType="TestUser"
    	>
    	SELECT
			*
		FROM
		 	${table_name} tu
		WHERE
			tu.user_id = #{user_id}
    </select>  

(尽量使用#{}传参,用预编译类型)

statementType=“STATEMENT”

当配置为非预编译时,则需要在整个语句中都采用${},而不能采用#{}
在通常情况下,都可以采用将整体配置为预编译的模式,然后针对需要不可以使用占位符的区域采用${}来传入参数,比如表名、列名、关键字等。

非预编译和预编译的区别在于

  • 非预编译没有缓存,每一次都要重新组合。
  • 预编译有占位符能防止SQL注入,非预编译没有

结语

原本是尝试一下怎么把表名输进去的,然后稍微了解了一下预编译和非预编译。结论就是尽量使用预编译功能,不论是性能和安全性。对此我存疑,如何对于不能使用预编译功能的输入参数进行管理呢
后续如果找到了方案我会在此更新:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值