问题描述:
我有 java.lang.NoSuchMethodException: bar.Foo.<init>(java.lang.Long, java.lang.String, java.util.Map)
当我试图用mybatis从db中获取不可变的foo对象,却无法找出问题所在时:(
我有一个不成功的案例,用@value注解结果对象,用@data注解成功的案例(它们在下面相应的标题下)。所以,我想使用@value,但不要理解我做错了什么。。
失败案例:
所以,我有一个不可变的结果类:
@Value
public class Foo {
long entryId;
String description;
Map<String, String> params;
}
它存储在postgres的foos表中, params
字段值以json格式存储在同一表的相应列中(类型为varchar,条目为 "{key=value}"
万一 params = Map.of("key", "value")
. 我想从db中示例化这个类的对象,因此我使用以下mybatis代码:
<resultMap id="foo" type="bar.Foo">
<constructor>
<arg column="entry_id" javaType="java.lang.Long"/>
<arg column="description" javaType="java.lang.String"/>
<arg column="params" javaType="java.util.Map" jdbcType="VARCHAR" typeHandler="bar.MapToJsonStringHandler"/>
</constructor>
</resultMap>
下面是我的类型处理程序(它已经在另一个案例中成功地使用了@data object而不是@value,所以我猜它本身是正确的):
public class MapToJsonStringHandler implements TypeHandler<Map<String, String>> {
private final ObjectMapper objectMapper = new ObjectMapper();
@SneakyThrows(IOException.class)
@Override
public void setParameter(PreparedStatement ps, int i, Map<String, String> parameter, JdbcType jdbcType) throws SQLException {
if (parameter == null) {
ps.setNull(i, Types.VARCHAR);
} else {
ps.setString(i, objectMapper.writeValueAsString(parameter));
}
}
@Override
public Map<String, String> getResult(ResultSet rs, String columnName) throws SQLException {
String result = rs.getString(columnName);
return convertToMap(result);
}
@Override
public Map<String, String> getResult(ResultSet rs, int columnIndex) throws SQLException {
String result = rs.getString(columnIndex);
return convertToMap(result);
}
@Override
public Map<String, String> getResult(CallableStatement cs, int columnIndex) throws SQLException {
String result = cs.getString(columnIndex);
return convertToMap(result);
}
@SneakyThrows(IOException.class)
private Map<String, String> convertToMap(String result) {
return result == null ? Collections.emptyMap() : objectMapper.readValue(result, Map.class);
}
}
以下是sql:
<select id="getFoos" resultMap="foo">
SELECT *
FROM foos
<![CDATA[WHERE needed_tm < now()]]>
</select>
当我拿到食物的时候 java.lang.NoSuchMethodException: bar.Foo.<init>(java.lang.Long, java.lang.String, java.util.Map)
.
有趣的是,当我使用@data而不是@value时,它就像一个符咒:
成功案例:
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Foo {
long entryId;
String description;
Map<String, String> params;
}
<resultMap id="foo" type="bar.Foo">
<result column="entry_id" property="entryId"/>
<result column="description" property="description"/>
<result column="params" property="params" typeHandler="bar.MapToJsonStringHandler"/>
</resultMap>
sql和类型处理程序与不成功的情况相同。
请你给我一个提示,我可能遗漏了什么?提前谢谢!
更新1:
@Value
@AllArgsConstructor
public class Foo {
long entryId;
String description;
Map<String, String> params;
}
给出了同样的例外。无论如何,据我所知,@value已经设计好了@allargsconstructor(https://projectlombok.org/features/value)
1条答案
按热度按时间6yt4nkrj1#
java.lang.nosuchmethodexception:bar.foo.(java.lang.long,java.lang.string,java.util.map)<---表示没有定义构造函数。
当您使用@allargsconstuctor时,您告诉lombok生成一个包含所有参数(long、string、map)的构造函数,这就是为什么它适合您的原因。
根据文件@数据:
@现在数据都在一起了:@tostring、@equalsandhashcode、@getter(所有字段)、setter(所有非最终字段)和@requiredargsconstructor的快捷方式
https://projectlombok.org/features/data
这就是为什么当您使用@data时,它会找到一个构造函数并且不会给您一个错误(nosuchmethod)。
因为您将数据类型指定为java.lang.long,所以它希望构造函数被定义为具有该参数类型。
我相信@data并不是构造器帮了你,而是setters(拳击)帮了你很久。
尝试使用@value,并在你的类中从long改为long。看看这样行不行。
lombok将生成一个构造函数,使用(long,string,map),not(long,string,map)
很想知道你用的是什么java版本。