Java MyBatis 枚举字符串值
Java MyBatis Enum string value
我觉得这是一个简单的问题,但 none 我尝试过的方法对我有用。我有一个枚举,我有字符串构造函数的原因是因为 Java 不允许枚举为数字。我直接尝试了 AA、AB、2C,但没有字符串构造函数,但这会出错。请注意,对于现有的枚举,我添加了 C("2C")。
public enum TestEnum{
AA("AA"), AB("AB"), C("2C");
private String display;
private TestEnum( String display ) {
this.display = display;
}
public String toString() {
return display;
}
public String getDisplay() {
return display;
}
public void setDisplay( String display ) {
this.display = display;
}
public String getName() {
return display;
}
现在我有一个 mybatis 映射器,它执行合并这是现有的,映射器的参数之一是 TestEnum。到目前为止,这工作正常,因为枚举值和字符串值相同,但我添加了 C("2C")。现在我想使用 mybaits 将 2C 插入 table,但它总是插入 C。
merge into text t
using (select #{id} as id from dual) d on (d.id = t.id)
when matched then
update set
appId = #{applId},
src = #{testEnum}
testEnum 插入 C,所以我将其更改为 #{testEnum.toString()} 这给了我一个没有 getter for 属性 name toString() 错误。我试过 #{testEnum.display} 和 #{testEnum.name} 它们仍然插入 C 而我希望它插入 2C。你们知道更简单的处理方法吗?
我不想更改模型对象以传递 String 而不是 TestEnum,因为这个对象在很多地方都被使用 places.Is 有一种方法可以在不更改模型对象的情况下在 mybatis 映射器中完成吗?
感谢您的帮助:)
你需要的是TypeHandler
首先,给你的 TestEnum
添加一个静态方法到 return 给定一个 TestEnum
显示字符串:
public static TestEnum fromDisplay(String display){
for (TestEnum v : TestEnum.values()){
if (v.getDisplay().equals(display)){
return v;
}
}
return null;
}
然后用它来创建你的 TypeHandler:
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
public class TestEnumTypeHandler extends BaseTypeHandler<TestEnum> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, TestEnum parameter, JdbcType jdbcType)
throws SQLException {
ps.setString(i, parameter.getDisplay());
}
@Override
public TestEnum getNullableResult(ResultSet rs, String columnName) throws SQLException {
return TestEnum.fromDisplay(rs.getString(columnName));
}
@Override
public TestEnum getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
return TestEnum.fromDisplay(rs.getString(columnIndex));
}
@Override
public TestEnum getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
return TestEnum.fromDisplay(cs.getString(columnIndex));
}
}
最后,在你的mybatis中注册你的TypeHandler xml:
<typeHandlers>
<typeHandler handler="blah.blah.TestEnumTypeHandler "/>
</typeHandlers>
除了@Malt 回答:
你尝试的方法不起作用的原因是 MyBatis EnumTypeHandler
默认设置方法的 name()
值并标有 final
所以你不能覆盖它:
EnumTypeHandler.class(第 38 至 44 行):
@Override
public void setNonNullParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType) throws SQLException {
if (jdbcType == null) {
ps.setString(i, parameter.name());
} else {
ps.setObject(i, parameter.name(), jdbcType.TYPE_CODE); // see r3589
}
}
否则,枚举是从方法 valueOf(type, name)
创建的,该方法也使用枚举的名称。
@Override
public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
String s = rs.getString(columnIndex);
return s == null ? null : Enum.valueOf(type, s);
}
@Override
public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
String s = cs.getString(columnIndex);
return s == null ? null : Enum.valueOf(type, s);
}
所以,您肯定需要使用特定的 typeHandler 来处理具有特定行为的枚举,但我会 extends
在特定的枚举类型处理程序中直接 EnumTypeHandler
,而不是 BaseTypeHandler
(Malt 回答),因为您可以重用某些功能(不是在您的情况下,但可能在其他情况下),因此它处理一般的枚举行为。
如果您想插入 Enum 的值,则无需编写任何自定义 TypeHandler
。
您唯一需要做的一件事就是在您的 MyBatis 插入中指定 getter 方法的名称。
示例:
SQL:
CREATE TABLE demo
(
id BIGINT,
value VARCHAR(10),
status CHAR(1)
);
MyBatis 映射器:
@Update("UPDATE demo SET status = #{status.value} WHERE id= #{uuid}")
long updateStatus(@Param("status") Status status, @Param("uuid") String uuid);
和 Java 枚举:
public enum Status {
ACTIVE("A"),
INACTIVE("I");
Status(final String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
在您的情况下,您可以在 SQL 中使用 src = #{testEnum.display}
。
我觉得这是一个简单的问题,但 none 我尝试过的方法对我有用。我有一个枚举,我有字符串构造函数的原因是因为 Java 不允许枚举为数字。我直接尝试了 AA、AB、2C,但没有字符串构造函数,但这会出错。请注意,对于现有的枚举,我添加了 C("2C")。
public enum TestEnum{
AA("AA"), AB("AB"), C("2C");
private String display;
private TestEnum( String display ) {
this.display = display;
}
public String toString() {
return display;
}
public String getDisplay() {
return display;
}
public void setDisplay( String display ) {
this.display = display;
}
public String getName() {
return display;
}
现在我有一个 mybatis 映射器,它执行合并这是现有的,映射器的参数之一是 TestEnum。到目前为止,这工作正常,因为枚举值和字符串值相同,但我添加了 C("2C")。现在我想使用 mybaits 将 2C 插入 table,但它总是插入 C。
merge into text t
using (select #{id} as id from dual) d on (d.id = t.id)
when matched then
update set
appId = #{applId},
src = #{testEnum}
testEnum 插入 C,所以我将其更改为 #{testEnum.toString()} 这给了我一个没有 getter for 属性 name toString() 错误。我试过 #{testEnum.display} 和 #{testEnum.name} 它们仍然插入 C 而我希望它插入 2C。你们知道更简单的处理方法吗?
我不想更改模型对象以传递 String 而不是 TestEnum,因为这个对象在很多地方都被使用 places.Is 有一种方法可以在不更改模型对象的情况下在 mybatis 映射器中完成吗?
感谢您的帮助:)
你需要的是TypeHandler
首先,给你的 TestEnum
添加一个静态方法到 return 给定一个 TestEnum
显示字符串:
public static TestEnum fromDisplay(String display){
for (TestEnum v : TestEnum.values()){
if (v.getDisplay().equals(display)){
return v;
}
}
return null;
}
然后用它来创建你的 TypeHandler:
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
public class TestEnumTypeHandler extends BaseTypeHandler<TestEnum> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, TestEnum parameter, JdbcType jdbcType)
throws SQLException {
ps.setString(i, parameter.getDisplay());
}
@Override
public TestEnum getNullableResult(ResultSet rs, String columnName) throws SQLException {
return TestEnum.fromDisplay(rs.getString(columnName));
}
@Override
public TestEnum getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
return TestEnum.fromDisplay(rs.getString(columnIndex));
}
@Override
public TestEnum getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
return TestEnum.fromDisplay(cs.getString(columnIndex));
}
}
最后,在你的mybatis中注册你的TypeHandler xml:
<typeHandlers>
<typeHandler handler="blah.blah.TestEnumTypeHandler "/>
</typeHandlers>
除了@Malt 回答:
你尝试的方法不起作用的原因是 MyBatis EnumTypeHandler
默认设置方法的 name()
值并标有 final
所以你不能覆盖它:
EnumTypeHandler.class(第 38 至 44 行):
@Override
public void setNonNullParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType) throws SQLException {
if (jdbcType == null) {
ps.setString(i, parameter.name());
} else {
ps.setObject(i, parameter.name(), jdbcType.TYPE_CODE); // see r3589
}
}
否则,枚举是从方法 valueOf(type, name)
创建的,该方法也使用枚举的名称。
@Override
public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
String s = rs.getString(columnIndex);
return s == null ? null : Enum.valueOf(type, s);
}
@Override
public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
String s = cs.getString(columnIndex);
return s == null ? null : Enum.valueOf(type, s);
}
所以,您肯定需要使用特定的 typeHandler 来处理具有特定行为的枚举,但我会 extends
在特定的枚举类型处理程序中直接 EnumTypeHandler
,而不是 BaseTypeHandler
(Malt 回答),因为您可以重用某些功能(不是在您的情况下,但可能在其他情况下),因此它处理一般的枚举行为。
如果您想插入 Enum 的值,则无需编写任何自定义 TypeHandler
。
您唯一需要做的一件事就是在您的 MyBatis 插入中指定 getter 方法的名称。
示例:
SQL:
CREATE TABLE demo
(
id BIGINT,
value VARCHAR(10),
status CHAR(1)
);
MyBatis 映射器:
@Update("UPDATE demo SET status = #{status.value} WHERE id= #{uuid}")
long updateStatus(@Param("status") Status status, @Param("uuid") String uuid);
和 Java 枚举:
public enum Status {
ACTIVE("A"),
INACTIVE("I");
Status(final String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
在您的情况下,您可以在 SQL 中使用 src = #{testEnum.display}
。