When carrying an ID, it is usually stored in an int, long, String, etc., but this may cause it to become confused and difficult to understand in the following cases.
public someMethod(int hogeId, int fugaId) { ... }
If you can do this, you can prevent careless mistakes. (If you make it chiguhagu, the IDE will give you an error.)
public someMethod(HogeId hogeId, FugaId fugaId) { ... }
While this is easier to understand, there are some points to be aware of.
@ RestController
It can be realized by the following.
PiyoId.java
package your.package;
import your.package.LongId;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
class PiyoId extends LongId {
public PiyoId(String id) { super(id); }
public PiyoId(long id) { super(id); }
}
LongId.java
package your.package;
import com.fasterxml.jackson.annotation.JsonValue;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode
public abstract class LongId {
private final long id;
public LongId(String id) {
this.id = Long.parseLong(id);
}
public LongIdBase(long id) {
this.id = id;
}
@JsonValue
public long getId() {
return this.id;
}
public String toString() {
return this.getClass().getSimpleName() + "(" + this.id + ")";
}
}
LongIdTypeHandler.java
package your.package;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import your.package.HogeId;
import your.package.LongId;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedTypes;
//List the ID classes here
@MappedTypes(value = {HogeId.class})
public class LongIdTypeHandler<E extends LongId> extends BaseTypeHandler<E> {
private final Class<E> type;
public LongIdTypeHandler(Class<E> type) {
if (type == null) throw new IllegalArgumentException("Type argument cannot be null");
this.type = type;
}
private E createInstance(boolean wasNull, long id) {
if (wasNull) {
return null;
}
try {
return type.getDeclaredConstructor(long.class).newInstance(id);
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
@Override
public void setNonNullParameter(PreparedStatement ps, int num, E parameter, JdbcType jdbcType) throws SQLException {
long id = rs.getLong(columnName);
return createInstance(rs.wasNull(), id);
}
@Override
public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
long id = rs.getLong(columnName);
return createInstance(rs.wasNull(), id);
}
@Override
public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
long id = rs.getLong(columnIndex);
return createInstance(rs.wasNull(), id);
}
@Override
public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
long id = cs.getLong(columnIndex);
return createInstance(cs.wasNull(), id);
}
}
To be able to convert seamlessly, it must be one of the following:
One of the following:
@JsonCreator
One of the following:
4. Judgment from getters
5. Method execution with @JsonValue
Correspond to 3 and 5
Both of the following need to be addressed:
--I want to specify parameterType =" com. ~ .PiyoId "
and retrieve it with the description# {id}
.
--This is as long as the method long getId ()
is defined in PiyoId
.
--I want to specify parameterType =" com. ~ .Piyo "
so that it can be retrieved with the description # {id}
.
--This requires the definition of TypeHandler. ~~ However, only setNonNullParameter
is implemented. getNullableResult
cannot be used because the concrete class is unknown and new cannot be done.
So that it can be converted to Object in ResultMap of MyBatis ~~ [2020/02/15 postscript] It is possible to make new by enumerating concrete classes in TypeHandler.
-[2020/02/15 postscript] When getting the auto generated column, the following does not work for some reason.
It doesn't work with selectKey
<insert id="insert" parameterType="your.package.Hoge">
INSERT INTO hoges (value1, value2)
VALUES (#{value1}, #{value2})
<selectKey resultType="your.package.HogeId" keyProperty="id" order="AFTER">
select @@IDENTITY
</selectKey>
</insert>
UseGeneratedKeys works
<insert id="insert" parameterType="your.package.Hoge" useGeneratedKeys="true" keyProperty="id">
INSERT INTO hoges (value1, value2)
VALUES (#{value1}, #{value2})
</insert>
Controller
parameters--In any of the following cases, I want to receive a parameter that comes with a numerical value such as 123 as a PiyoId
type.
--@PathVariable ("piyoId") PiyoId piyoId
--When receiving as @RequestBody PiyoForm form
or @ModelAttribute PiyoForm form
, and when receiving as PiyoId
type in form
--Normal error: Caused by: java.lang.IllegalStateException: Cannot convert value of type'java.lang.String' to required type'your.package.PiyoId': no matching editors or conversion strategy found
--Conclusion: You can do this if your ID class has a constructor that accepts a String.
@ RestController
return value--If PiyoId
is mixed, I want to convert it to JSON as a numerical value.
--Conclusion: This is okay if it supports Jackson mentioned above.
--In some cases, new was required to create the ID, and the hash value calculation became complicated, but even if it was rotated 10 million times, there was almost no difference in about 1.5 seconds between the two. If it is a long type, there is a load of Boxing, so after all it is a ton ton?
verification code
//Write later
Recommended Posts