Java的SQL语句的写法小结

本文总结了Java中构建SQL语句时遇到的字符串处理问题,指出双引号用于表示SQL字符串,单引号用于字符串字段,加号用于连接字符串。理解这些符号的含义有助于更好地编写和理解Java中的SQL语句。

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

Java的strSQL的写法确实有时候让人头疼:有' " +让你搞得不是很明白。

其实,分开来看就行。识别每个符号的意思即可。

"" 是SQL的字符串。是String类型的。

' '里主要用来字符串操作的。和数据库的varchar等相对应得。不和int 对应。

+ 是用来连接字符串类的

 这样你就可以看明白了。

<think>我们正在解决一个MyBatis参数绑定异常:`TypeException: Could not set parameters for mapping`,具体是关于`deptName`参数,错误提示为`JdbcType OTHER`导致的无效列类型(错误代码1111)。根据引用[1]中的描述,这个异常通常是因为MyBatis无法确定参数的JDBC类型。 ### 问题分析 1. **根本原因**:当MyBatis尝试设置参数时,如果未指定`jdbcType`,且参数值为`null`,MyBatis会尝试使用`OTHER`类型(即未知类型)。但某些数据库驱动(如Oracle)不支持`OTHER`类型,导致出现“无效的列类型”错误。 2. **常见场景**:在传入参数为`null`时,MyBatis无法从Java类型推断出合适的JDBC类型。 3. **解决方案**:在映射文件中为可能为`null`的参数显式指定`jdbcType`。 ### 解决步骤 #### 1. 在SQL映射文件中指定`jdbcType` 在参数占位符中,使用`#{property, jdbcType=TYPE}`格式明确指定JDBC类型。例如: ```xml <insert id="insertDept"> INSERT INTO dept(dept_id, dept_name) VALUES(#{deptId}, #{deptName, jdbcType=VARCHAR}) </insert> ``` - **关键点**:为`deptName`指定`jdbcType=VARCHAR`,即使它为`null`,数据库也能正确处理。 #### 2. 全局配置(可选但推荐) 在MyBatis全局配置文件(如`mybatis-config.xml`)中开启对`null`值的自动映射: ```xml <configuration> <settings> <!-- 指定当参数为null时,默认的JDBC类型为NULL(避免使用OTHER) --> <setting name="jdbcTypeForNull" value="NULL"/> </settings> </configuration> ``` - **作用**:当参数为`null`且未指定`jdbcType`时,默认使用`NULL`类型而非`OTHER`。 #### 3. 检查参数类型一致性 确保Java实体类中`deptName`的类型与数据库字段类型兼容: - 实体类示例: ```java public class Dept { private Long deptId; private String deptName; // 应为String类型 // getters/setters } ``` - 若数据库字段为`VARCHAR2`(Oracle)或`VARCHAR`,则Java类型应为`String`。 #### 4. 验证参数值 确保传入的`deptName`值不是导致类型转换失败的特殊值(如非字符串对象)。 ### 错误示例与修正对比 - **错误写法**(未指定`jdbcType`): ```xml #{deptName} <!-- 当deptName=null时,MyBatis尝试使用OTHER类型 --> ``` - **正确写法**: ```xml #{deptName, jdbcType=VARCHAR} ``` ### 扩展:为什么会出现`OTHER`类型? - MyBatis通过Java类型推断JDBC类型。如果参数为`null`,无法推断类型,则回退到`OTHER`。 - 数据库驱动对`OTHER`支持不一致(如Oracle驱动会报错),因此必须显式指定。 ### 总结解决方案 1. **局部方案**:在SQL映射文件中为每个可能为`null`的参数添加`jdbcType`(如`VARCHAR`、`INTEGER`等)。 2. **全局方案**:在配置文件中设置`jdbcTypeForNull=NULL`,统一处理`null`值。 3. **辅助检查**:确认实体类属性与数据库字段类型匹配。 通过上述步骤,即可解决参数绑定时因`JdbcType OTHER`导致的无效列类型错误。 --- ### 相关问题 1. MyBatis 中如何全局配置 `jdbcTypeForNull` 以避免 `OTHER` 类型错误? 2. 除了指定 `jdbcType`,还有哪些方法可以处理 MyBatis 参数为 `null` 的情况? 3. MyBatis 在调用存储过程时出现参数类型不匹配错误如何解决? [^1]: nested exception is org.apache.ibatis.type.TypeException: Could not set parameters for mapping: ParameterMapping{property='deptId', mode=IN, javaType=class java.lang.Long, jdbcType=null, numericScale=null, resultMapId='null', jdbcTypeName='null', expression='null'}. Cause: org.apache.ibatis.type.TypeException: Error setting non null for parameter #4 with JdbcType null . Try setting a different JdbcType for this parameter or a different configuration property. Cause: java.sql.SQLException: 无效的列索引 [^2]: mybatis会为接口自动的创建一个代理对象,代理对象去执行增删改查方法 测试 @Test public void test2() throws IOException { SqlSessionFactory sqlSessionFactory = get(); SqlSession sqlSession = sqlSessionFactory.openSession(); EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class); Employee emp = mapper.getEmpById(1); System.out.println(emp); sqlSession.close(); } 小结 sqlSession和connection一样都是现成非安全的,代表个数据库的一次回话,用完必须关闭,每次使用都应该去获取新的对象Mapper接口没有实现类,但是mybatis会为这个借口生成一个代理对象,将接口和xml进行绑定两个配置文件:mybatis的全局配置文件,包含数据库连接池信息,事务管理器信息等系统运行环境;sql映射文件,包含了每一个sql语句的映射信息 mapper.xml文件位置 [^3]: 1、不要一个大而全的数据更新接口,传入为POJO类,不管是不是自己的目标更新字段,都进行 update table set c1= value1,c2 = value2, c3 = value3;这是不对的。 执行SQL时,不要更新无改动的字段,一是易出错;二是效率低;三是增加binlog存储。 5.2、使用Mybatis 批量查询数据时,查询条件为null造成报错 20211113 [^4]: 仅仅简化SQL的编 常见框架模式Hibernate框架偏向简化SQL的模式MyBatis框架偏向ORM的模式国内使用MyBatis相对较多(MyBatisPlus 做SQL生成)Spring内部提供的JdbcTemplate偏向简化SQL的模式JPA完全倒向了ORM的形式,建表的过程都被抽象,我们看到的只有类(我了类,框架根据类建表) 1-3 认识 MyBatis</think>### 解决 MyBatis 参数绑定失败问题:`JdbcType OTHER`导致的无效列类型错误 #### 问题分析(基于错误信息) ```log TypeException: Could not set parameters for mapping: ParameterMapping{property='deptName', ... jdbcType=null ...} Cause: java.sql.SQLException: 无效的列索引 1111 ``` 根本原因是 **MyBatis 无法自动推断参数的 JDBC 类型**(特别是当参数值为 `null` 时),导致使用了不兼容的 `OTHER` 类型。以下是具体原因: 1. **未显式指定 jdbcType**:当参数值为 `null` 时,MyBatis 无法从 Java 类型推断 JDBC 类型 2. **数据库驱动兼容性**:某些数据库(如 Oracle)不支持 `OTHER` 类型 3. **参数类型冲突**:Java 类型(如 `String`)与数据库字段类型(如 `VARCHAR2`)映射不明确 --- ### 解决方案(分步骤操作) #### 1. 显式指定参数的 JDBC 类型(推荐) 在 SQL 映射文件中为参数添加 `jdbcType` 属性: ```xml <!-- 修改前(错误示例) --> #{deptName} <!-- 修改后(正确示例) --> #{deptName, jdbcType=VARCHAR} ``` - **关键点**:根据数据库字段类型选择正确的 `jdbcType`: - `VARCHAR`(适用于 MySQL/SQL Server) - `NVARCHAR`(适用于 Oracle 的 Unicode 字段) - `VARCHAR2`(Oracle 专用) #### 2. 全局配置 JDBC 类型处理(备选) 在 `mybatis-config.xml` 中添加全局设置: ```xml <configuration> <settings> <!-- 指定 null 值的默认 JDBC 类型 --> <setting name="jdbcTypeForNull" value="NULL"/> </settings> </configuration> ``` > **注意**:此配置会使所有未指定 `jdbcType` 的 `null` 参数使用 `NULL` 类型而非 `OTHER`[^1] #### 3. 检查参数类型一致性 确保 Java 实体类与数据库字段类型匹配: ```java public class Dept { // Oracle 建议使用 String(对应 VARCHAR2/NVARCHAR2) private String deptName; // PostgreSQL/MySQL 可使用 String(对应 VARCHAR) } ``` #### 4. 验证 SQL 参数索引 检查参数占位符顺序是否与接口方法参数一致: ```xml <!-- 示例:参数索引从0开始 --> <select id="selectDept"> SELECT * FROM dept WHERE dept_name = #{0, jdbcType=VARCHAR} <!-- 第一个参数 --> </select> ``` --- ### 错误示例 vs 正确示例 | 场景 | 错误写法 | 正确写法 | |------|----------|----------| | **普通参数** | `#{deptName}` | `#{deptName, jdbcType=VARCHAR}` | | **List 参数** | `#{item}` | `#{item, jdbcType=VARCHAR}` | | **Oracle 字段** | `#{deptName}` | `#{deptName, jdbcType=NVARCHAR}` | --- ### 根本原因深度解析 1. **类型推断机制缺陷** MyBatis 通过 `ParameterMapping` 获取参数类型,当值为 `null` 时,默认使用 `OTHER` 类型[^1] 2. **数据库驱动限制** Oracle JDBC 驱动会拒绝 `OTHER` 类型,抛出 `SQLException: 无效的列索引`[^3] 3. **动态 SQL 风险点** 当使用 `<if>` 动态拼接 SQL 时,更易出现未显式指定类型的参数[^3] > **最佳实践**:始终为可能为 `null` 的参数指定 `jdbcType`,尤其在 Oracle 环境中。 --- ### 相关问题 1. MyBatis 中如何为存储过程参数指定 `jdbcType`? 2. 使用 MyBatis 操作 Oracle 数据库时有哪些特殊类型注意事项? 3. 如何全局配置 MyBatis 处理 `null` 值的 JDBC 类型? [^1]: nested exception is org.apache.ibatis.type.TypeException: Could not set parameters for mapping: ParameterMapping{property='deptId', mode=IN, javaType=class java.lang.Long, jdbcType=null,... Cause: java.sql.SQLException: 无效的列索引 [^2]: mybatis会为接口自动的创建一个代理对象,代理对象去执行增删改查方法 [^3]: 不要一个大而全的数据更新接口... 执行SQL时,不要更新无改动的字段,一是易出错;二是效率低;三是增加binlog存储 [^4]: MyBatis框架偏向ORM的模式... 建表的过程都被抽象,我们看到的只有类
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值