I feel like this is a simple problem, but none of the things i tried work for me. I have an enum, the reason i have string constructor is because Java doesn't allow enum to be numerical..I tried AA, AB, 2C directly without string constructor but that gives an error. Note that for the existing enum i am adding 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;
}
Now i have a mybatis mapper which does a merge this is existing and one of the param to the mapper is TestEnum. Until now this worked fine since enum value and string value are same, but i added C("2C"). Now i want to insert 2C to the table using mybaits, but it always inserts 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 inserts C, so i changed that to #{testEnum.toString()} which gave me a there is no getter for property name toString() error. I tried #{testEnum.display} and #{testEnum.name} both of them still inserts C whereas i want it to insert 2C. Do you guys know an easier way of handling this?
I don't want to change the model object to pass String rather than TestEnum because this object is being used in many places.Is there a way this can be done in the mybatis mapper without changing model object?
Thanks for your help :)
What you need is a TypeHandler
First, add a static method to your TestEnum
to return a TestEnum
given a display string:
public static TestEnum fromDisplay(String display){
for (TestEnum v : TestEnum.values()){
if (v.getDisplay().equals(display)){
return v;
}
}
return null;
}
Then use it to create your 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));
}
}
Finally, register your TypeHandler in your mybatis xml:
<typeHandlers>
<typeHandler handler="blah.blah.TestEnumTypeHandler "/>
</typeHandlers>
You do not need to write any custom TypeHandler
if you want to insert the value of your Enum.
The only one thing you need to do is to specify the getter method's name in your MyBatis insert.
Example:
SQL:
CREATE TABLE demo
(
id BIGINT,
value VARCHAR(10),
status CHAR(1)
);
MyBatis mapper:
@Update("UPDATE demo SET status = #{status.value} WHERE id= #{uuid}")
long updateStatus(@Param("status") Status status, @Param("uuid") String uuid);
And the Java Enum:
public enum Status {
ACTIVE("A"),
INACTIVE("I");
Status(final String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
In your case you can use src = #{testEnum.display}
in your SQL.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With