How to read nested optional object for an insert statement?
I have the following classes;
public class MyObj {
private String myField;
private MyChildObj myChild;
public (String myField, MyChildObj myChild) {
this.myField = myField;
this.myChild = myChild;
}
public String getMyField() {
return this.myField;
}
public Optinal<MyChildObj> getMyChildObj() {
return Optional.ofNullable(this.myChild);
}
}
public class MyChildObj {
private String myField2;
public (String myField2) {
this.myField2 = myField2;
}
public String getMyField2() {
return this.myField2;
}
}
And a mapper like this:
public interface MyMapper {
@Insert("INSERT INTO `Entity` VALUES(" +
"#{entity.myField}," +
"#{entity.myChild.myField2})")
public int insertEntity(@Param("entity") MyObj entity);
With this I get an error like
There is no getter for property named 'myField2' in 'class java.util.Optional'
Do I need a separate TypeHandler for this or is there another solution?
In your example, the getter name is different from the field name.
In this case, you can access the field directly in a mapper statement because MyBatis can access private field/method [1].
When the getter has the same name as the field, there needs to be some extra work.
I'll explain the following three solutions.
<bind>tag.ObjectWrapper.The first one is pretty straight-forward.
Just add a private getter method...
...and use it in a mapper statement.
The second solution is a little bit verbose.
In a
<bind>tag, the expression ofvalueattribute is evaluated by OGNL, so you can write something like the following.The third solution is to create a custom
ObjectWrapper.The following implementation adds a pseudo property
orNulltoOptionalobjects (note: it's not well-tested).To register the custom
ObjectWrapperFactoryusing MyBatis' XML configuration:If you are using mybatis-spring-boot, add the following line to the
application.properties:The pseudo-property
orNullreturnsnullwhen theOptionalis empty.[1] With JPMS, you may have to open your module to MyBatis.