1. Question:
Assume such a scenario
The value in localurl is roughly like this:
dwad21.jpg, dwad22.jpg, dwad.23.jpg
is a string
If I have a field (local_url) in the sql table that is the concatenation value of multiple url strings of local image resources. I want to get value plus value without extra conversion in java backend. What I need is the dwad21.jpg inside, it is best to do collection processing.
The best situation is to turn the string into a collection when using sql to map to an object dwad21.jpg, dwad22.jpg, dwad.23.jpg
=> {dwad21. jpg,dwad22.jpg,dwad.23.jpg}
Then automatically turn the collection into a string when using insert or update {dwad21.jpg, dwad22.jpg, dwad.23.jpg}
=>dwad21.jpg,dwad22.jpg ,dwad.23.jpg
2. Solution:
2.1.Typehandler official website introduction
It mainly performs custom mapping processing on request data or received data.
I can only say that mybaits is very arbitrary and provides a custom type converter.
mybatis official website=>Configuration=>Type processor
“———————————————— ——————》
Function: When MyBatis sets parameters in a prepared statement (PreparedStatement) or retrieves a value from the result set, it will use a type processor to convert the obtained value into a Java type in an appropriate manner.
The following are the default type handlers for commonly used data types.
Type Handler | Java Type=>JDBC Type |
---|---|
BooleanTypeHandler | java.lang.Boolean,boolean =>BOOLEAN |
ByteTypeHandler | java.lang.Byte,byte => NUMERIC, BYTE |
ShortTypeHandler | java.lang.Short, short =>NUMERIC, SMALLINT |
IntegerTypeHandler | java.lang.Integer, int =>NUMERIC, INTEGER |
LongTypeHandler | java.lang.Long, long => NUMERIC, BIGINT |
FloatTypeHandler | java.lang.Float, float => NUMERIC, FLOAT |
DoubleTypeHandler | java.lang.Double, double=> NUMERIC ,DOUBLE |
BigDecimalTypeHandler | java.math.BigDecimal => NUMERIC, DECIMAL |
StringTypeHandler | java.lang.String => CHAR, VARCHAR |
2.2. Create a custom handler
You can override existing type handlers or create your own to handle unsupported or nonstandard types. The specific steps are:
- Implement the
org.apache.ibatis.type.TypeHandler
interface,- Inherits a convenience class
org.apache.ibatis.type.BaseTypeHandler
and can (optionally) map it to a JDBC type. for example:
In most usage scenarios, mybaitis’s default type converter can help you convert java objects to jdbc objects.
But my whole flower life is obviously not satisfying. It just so happens that mybatis allows us to customize class converters.
Here we use the implementation interface
method to declare the type controller.
public class StringToListTypeHandler implements TypeHandler<List<String>> {<!-- --> @Override public void setParameter(PreparedStatement ps, int i, List<String> parameter, JdbcType jdbcType) throws SQLException {<!-- --> if (parameter != null) {<!-- --> ps.setString(i, String.join(",", parameter)); } else {<!-- --> ps.setNull(i, jdbcType.TYPE_CODE); } } @Override public List<String> getResult(ResultSet rs, String columnName) throws SQLException {<!-- --> String columnValue = rs.getString(columnName); return convertStringToList(columnValue); } @Override public List<String> getResult(ResultSet rs, int columnIndex) throws SQLException {<!-- --> String columnValue = rs.getString(columnIndex); return convertStringToList(columnValue); } @Override public List<String> getResult(CallableStatement cs, int columnIndex) throws SQLException {<!-- --> String columnValue = cs.getString(columnIndex); return convertStringToList(columnValue); } private List<String> convertStringToList(String columnValue) {<!-- --> if (columnValue != null) {<!-- --> return Arrays.asList(columnValue.split(",")); } else {<!-- --> return null; } } }
-
setParameter
method: This method is used to set the parameters of a Java object into a PreparedStatement, usually used to bind parameters to placeholders in SQL statements. In this example, it converts the List type parameter to a comma-separated string and sets it into a PreparedStatement. If the parameter is null, it will be set to the null value of the database type. -
getResult(ResultSet rs, String columnName)
: Obtain the result from the ResultSet object and obtain the corresponding column value according to the column name columnName. -
getResult(ResultSet rs, int columnIndex)
: Obtain the result from the ResultSet object and obtain the corresponding column value according to the column index columnIndex. -
getResult(CallableStatement cs, int columnIndex)
: Obtain the result from the CallableStatement object and obtain the corresponding column value according to the column index columnIndex. Typically this scenario is used to get results from stored procedures.
Generally only one method can be implemented
2.3. Register type converter
Note that MyBatis does not determine which type to use by detecting database metainformation, so you must specify that the field is of VARCHAR type in the parameter and result mapping
<typeHandlers> <typeHandler handler="com.chen.behindimagesmanage.handler.StringToListTypeHandler" javaType="java.util.List<java.lang.String>" jdbcType="VARCHAR"/> </typeHandlers>
Of course, aliases can also be configured here. If the type is set here in the mapper, there is no need to set it.
2.4. mapper uses type converter
- mapper xml file
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.chen.behindimagesmanage.dao.FileDao"> <!-- Define a query statement --> <resultMap id="imageMetaDataResultMap" type="com.chen.behindimagesmanage.pojo.ImageMetaData"> <id property="id" column="id" /> <result property="md5" column="md5" /> <result property="aliyunUrl" column="aliyun_url" /> <result property="localUrl" column="local_url" typeHandler="com.chen.behindimagesmanage.handler.StringToListTypeHandler" /> <result property="version" column="version" /> </resultMap> <select id="getAllImg" resultType="com.chen.behindimagesmanage.pojo.ImageMetaData"> SELECT * FROM image_metadata </select> <!-- Define an update statement --> <parameterMap id="imageMetaDataParamMap" type="com.chen.behindimagesmanage.pojo.ImageMetaData"> <parameter property="id" jdbcType="INTEGER" javaType="java.lang.Integer" mode="IN"/> <parameter property="md5" jdbcType="VARCHAR" javaType="java.lang.String" mode="IN"/> <parameter property="aliyunUrl" jdbcType="VARCHAR" javaType="java.lang.String" mode="IN"/> <parameter property="localUrl" typeHandler="com.chen.behindimagesmanage.handler.StringToListTypeHandler"/> <parameter property="version" jdbcType="INTEGER" javaType="int" mode="IN"/> </parameterMap> <update id="updateLocalUrl" > UPDATE image_metadata SET local_url= #{localUrl,typeHandler = com.chen.behindimagesmanage.handler.StringToListTypeHandler}, version = #{localUrl} + 1 WHERE version = #{vsersion} </update> </mapper>
- mapper interface layer
@Mapper public interface FileDao {<!-- --> /** * Get all img ownership information * @return all ownership information */ List<ImageMetaData> getAllImg(); /** * Update metadata belonging server * @param imageMetaData updated metadata column * @return affected row */ int updateLocalUrl(ImageMetaData imageMetaData); }