当前位置: 首页 > 知识库问答 >
问题:

用MyBatis映射输入和输出参数

益稳
2023-03-14

我正在学习如何使用Mybatis。老实说,我很喜欢这个框架。它很容易使用,我对它很满意,因为我可以使用它的sql命令:)我使用MyBatis 3.4.2和PostgreSQL数据库。

例如,我喜欢在插入之前使用@selectkey注释执行查询是多么容易。如果我在接口方法之前添加一些注释,那么数据映射就像一个迷人的例子,比如:@results({@result(property=“javafield”,column=“database_field”,javaType=typehandler.class)

我不喜欢的(我希望你能把我引向正确的方向)有以下几点:

SELECT * FROM table
WHERE key_name = ? AND ((? IS NULL AND user_id IS NULL) OR User_id = ?) 

使用JDBC时,我需要做到以下几点:

stmt = connection.prepareStatement(query);
stmt.setString(1, "key");
stmt.setString(2, userId);
stmt.setString(3, userId);

正如您所看到的,我需要传递两次用户ID,因为这是JDBC的工作方式。老实说,我希望下面的代码能够与MyBatis一起使用,但不幸的是,它不起作用。第三个参数仍然需要定义。

我想知道是否有可能在MyBatis中添加这个功能。如果MyBatis可以自动绑定userId两次,这应该很好,如下所示:

@Select("SELECT * FROM table key_name = #{key} and ((#{userId} is null and user_id is null) OR user_id = #{userId})
SomeClass findByKeyAndUserId(String key, Long userId);
@Select("SELECT * FROM table WHERE key_name = #{key} AND COALESCE(user_id, -1) = #{userId}")
SomeClass findByKeyAndUserId(String key, Long userId);

userId = (userId == null) ? -1 : userId;
SomeClass abc = mapper.findByKeyAndUserId(key, userId);
@Select("SELECT * FROM table WHERE ...")
@Results({
        @Result(property = "key", column = "key_name", javaType = String.class),
        @Result(property = "value", column = "key_value", javaType = String.class),
        @Result(property = "userId", column = "user_id", javaType = Long.class),
        @Result(property = "interval", column = "interval", javaType = Long.class),
        @Result(property = "description", column = "description", javaType = String.class),
        @Result(property = "status", column = "status", typeHandler = StatusTypeHandler.class)
})
SomeClass findByKeyAndUserId(@Param("key") String key, @Param("userId") Long userId);
@Select("SELECT * FROM table WHERE <different conditions then before>")
@Results({
        <I need to add here the exact same code then before in query 1>
})
SomeClass findByKeyAndUserId(@Param("key") String key, @Param("userId") Long userId);

我能以某种方式重用映射相关的代码吗?我需要添加映射,因为我对状态字段使用特殊的类型处理程序。我使用基于注释的配置。

(问题3)@param注释我在文档中看不到任何关于@param注释的内容。这很难理解为什么我的java参数没有被正确地绑定。最后,我意识到代码中缺少@param注释。为什么官方文件中没有提到这一点?我做了一些错误的事情,@param不需要使用?

该代码运行良好:

SomeClass findByKeyAndUserId(@Param("key") String key, @Param("userId") Long userId);

这不起作用:

SomeClass findByKeyAndUserId(String key, Long userId);

更新(问题1)

org.apache.ibatis.exceptions.PersistenceException: 
### Error querying database.  Cause: org.postgresql.util.PSQLException: ERROR: could not determine data type of parameter $2
### The error may exist in com/.../dao/TableDao.java (best guess)
### The error may involve ....dao.Table.findByKeyAndUserId-Inline
### The error occurred while setting parameters
### SQL: SELECT * FROM table WHERE key_name = ? AND (? IS NULL AND user_id IS NULL) OR user_id = ? AND status = 1
### Cause: org.postgresql.util.PSQLException: ERROR: could not determine data type of parameter $2

(问题1:解决方案2)我从postgres返回无法确定参数$2错误的数据类型的原因是,如果值为null,JDBC驱动程序无法确定参数的类型。所以让我们手动定义它。

@Select("SELECT * FROM table "
        + "WHERE key_name = #{key} AND ((#{userId}::BIGINT IS NULL AND user_id IS NULL) OR user_id = #{userId})")
})
SomeClass findByKeyAndUserId(@Param("key") String key, @Param("userId") Long userId);

(问题1:解决方案3)第二个解决方案依赖于PorstgreSQL。下面的解决方案完全独立于数据库。感谢@BlackWizard的精彩评论。

@Select("SELECT * FROM table "
        + "WHERE key_name = #{key} AND ((#{userId, jdbcType=BIGINT} IS NULL AND user_id IS NULL) OR user_id = #{userId})")
})
SomeClass findByKeyAndUserId(@Param("key") String key, @Param("userId") Long userId);

就我个人而言,我更喜欢解决方案3。它包含更少的附加代码。

共有1个答案

孔征
2023-03-14

问题1:

命名参数:

@Select("SELECT * FROM table key_name = #{key} and ((#{userId} is null and user_id is null) OR user_id = #{userId}")
SomeClass findByKeyAndUserId(@Param("key") String key, @Param("userId") Long userId);

Mybatis确实通过名称绑定参数,然后一次,两次,N次,就像引用它的时候一样,它可以工作。

@Select({"<script>",
         "<if 'userId==null'><bind name='userId' value='1'/></if>",
         "SELECT * FROM table WHERE key_name = #{key} ", 
         "AND COALESCE(user_id, -1) = #{userId}", 
         "</script>"})
SomeClass findByKeyAndUserId(@Param("key") String key, @Param("userId") Long userId);

问题2:您肯定不能重用/互化您在注释中定义的内容。这不是因为Mybatis,而是因为注释。您必须在XML中定义结果映射,并用@ResultMap引用它们。文件指出:

ResultMap   Method  N/A     This annotation is used to provide the id of a <resultMap> element in an XML mapper to a @Select or @SelectProvider annotation. This allows annotated selects to reuse resultmaps that are defined in XML. This annotation will override any @Results or @ConstructorArgs annotation if both are specified on an annotated select.

问题3:正如我在您的另一个问题中所回答的,@param注释具有将方便的参数列表转换为映射的作用,例如:

Map<String, Object> params = new HashMap<String, Object>();
params.put("key", key);
params.put("userId", userId);

我同意Mybatis文档可能会更好,您将在这里找到更多的资源。

@Param  Parameter   N/A     If your mapper method takes multiple parameters, this annotation can be applied to a mapper method parameter to give each of them a name. Otherwise, multiple parameters will be named by their position prefixed with "param" (not including any RowBounds parameters). For example #{param1}, #{param2} etc. is the default. With @Param("person"), the parameter would be named
#{person}.
 类似资料:
  • 本文向大家介绍MyBatis输入映射和输出映射实例详解,包括了MyBatis输入映射和输出映射实例详解的使用技巧和注意事项,需要的朋友参考一下 什么是 MyBatis ? MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以对配置和原生Map使用简单的 XML 或注解,将接口

  • 本文向大家介绍Mybatis输入输出映射及动态SQL Review,包括了Mybatis输入输出映射及动态SQL Review的使用技巧和注意事项,需要的朋友参考一下 一、输入映射     通过parameterType指定输入参数的类型,可以是简单类型、pojo包装类、HashMap等 1、输入简单类型 2、输入pojo包装类      Pojo类可根据业务需求,创建某单一实体的扩展实体,Use

  • 我正在学习Hadoop,并尝试执行我的Mapduce程序。所有Map任务和Reduce er任务都完成得很好,但Reducer将Mapper Output写入Output文件。这意味着根本没有调用Reduce函数。我的示例输入如下所示 预期输出如下所示 以下是我的计划。 这里问了同样的问题,我在reduce函数中使用了Iterable值作为该线程中建议的答案。但这并不能解决问题。我不能在那里发表评

  • 输出 用print加上字符串,就可以向屏幕上输出指定的文字。比如输出'hello, world',用代码实现如下: >>> print 'hello, world' print语句也可以跟上多个字符串,用逗号“,”隔开,就可以连成一串输出: >>> print 'The quick brown fox', 'jumps over', 'the lazy dog' The quick brown

  • 输出 用print()在括号中加上字符串,就可以向屏幕上输出指定的文字。比如输出'hello, world',用代码实现如下: >>> print('hello, world') print()函数也可以接受多个字符串,用逗号“,”隔开,就可以连成一串输出: >>> print('The quick brown fox', 'jumps over', 'the lazy dog') The qu

  • MapReduce传递和发出键值对的基本信息。我需要弄清楚我们通过什么和发出什么。以下是我的关注点:MapReduce输入和输出: 1.Map() 方法 - 它是否采用单个或列表的键值对并发出什么?2.对于每个输入键值对,发出什么映射器?相同类型还是不同类型 ?3.对于每个中间键,减速器会发出什么?类型是否有任何限制?4.减速机接收所有具有相同键的值。值将如何排序,如排序或轨道排序?该顺序是否因运