In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-03-29 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Database >
Share
Shulou(Shulou.com)06/01 Report--
Introduction to Mybatis type conversion
1.1 directory
1.2 establish TypeHandler
1.2.1 TypeHandler interface
1.2.2 BaseTypeHandler Abstract Class
1.3 sign up for TypeHandler
1.4 Mybatis automatically acquires TypeHandler
Automatic registration of TypeHandler in 1.5 Mybatis
1.2 establish TypeHandler
We know that java has the data type of java, and the database has the data type of database, so when we insert data into the database, how do we insert the java type into the database as the database type, and how do we treat the database type as the java type when reading data from the database? There must be a type conversion in between. In Mybatis, we can define something called a TypeHandler type handler, through which we can convert Java types to database types. Here is a brief introduction to how to build your own TypeHandler.
1.2.1 TypeHandler interface
To implement our own TypeHandler in Mybatis, we need to implement the TypeHandler interface provided by Mybatis. Four methods are defined in TypeHandler:
Java code
Public interface TypeHandler {
/ * *
* used to define how to convert parameters of type Java to corresponding database types when setting parameters in Mybatis
* @ param ps current PreparedStatement object
* @ param I location of the current parameter
* @ param parameter the Java object of the current parameter
* @ param jdbcType database type of the current parameter
* @ throws SQLException
, /
Void setParameter (PreparedStatement ps, int I, T parameter
JdbcType jdbcType) throws SQLException
/ * *
* used to convert the database type to the corresponding Java type when Mybatis acquires the data result set
* @ param rs's current result set
* @ param columnName current field name
* @ return converted Java object
* @ throws SQLException
, /
T getResult (ResultSet rs, String columnName) throws SQLException
/ * *
* used to convert the database type to the corresponding Java type when Mybatis obtains the field data through the field location
* @ param rs's current result set
* @ param columnIndex location of the current field
* @ return converted Java object
* @ throws SQLException
, /
T getResult (ResultSet rs, int columnIndex) throws SQLException
/ * *
* used by Mybatis to convert data of database type to corresponding Java type after calling stored procedure
* @ param cs CallableStatement after the execution of the current CallableStatement
* @ param columnIndex location of the current output parameter
* @ return
* @ throws SQLException
, /
T getResult (CallableStatement cs, int columnIndex) throws SQLException
}
Now suppose we have an entity object, User, where one of the attributes, interests, is of type String, as follows:
Java code
Public class User {
Private int id
Private String name
Private int age
Private String [] interests
Public int getId () {
Return id
}
Public void setId (int id) {
This.id = id
}
Public String getName () {
Return name
}
Public void setName (String name) {
This.name = name
}
Public int getAge () {
Return age
}
Public void setAge (int age) {
This.age = age
}
Public String [] getInterests () {
Return interests
}
Public void setInterests (String [] interests) {
This.interests = interests
}
@ Override
Public String toString () {
Return "User [age=" + age + ", id=" + id + ", interests="
+ Arrays.toString (interests) + ", name=" + name + "]"
}
}
We need to store it in the database as a concatenated string, and then restore it to a String array when we take it out. At this point, we can define a TypeHandler for it to handle the conversion between String array types and database VARCHAR types. Here we create a TypeHandler called StringArrayTypeHandler, with the code as follows:
Java code
Package com.tiantian.mybatis.handler
Import java.sql.CallableStatement
Import java.sql.PreparedStatement
Import java.sql.ResultSet
Import java.sql.SQLException
Import java.sql.Types
Import org.apache.ibatis.type.JdbcType
Import org.apache.ibatis.type.TypeHandler
Public class StringArrayTypeHandler implements TypeHandler {
Public String [] getResult (ResultSet rs, String columnName)
Throws SQLException {
String columnValue = rs.getString (columnName)
Return this.getStringArray (columnValue)
}
Public String [] getResult (ResultSet rs, int columnIndex)
Throws SQLException {
String columnValue = rs.getString (columnIndex)
Return this.getStringArray (columnValue)
}
Public String [] getResult (CallableStatement cs, int columnIndex)
Throws SQLException {
/ / TODO Auto-generated method stub
String columnValue = cs.getString (columnIndex)
Return this.getStringArray (columnValue)
}
Public void setParameter (PreparedStatement ps, int I, String [] parameter
JdbcType jdbcType) throws SQLException {
If (parameter = = null)
Ps.setNull (I, Types.VARCHAR)
Else {
StringBuffer result = new StringBuffer ()
For (String value: parameter)
Result.append (value) .append (",")
Result.deleteCharAt (result.length () 1)
Ps.setString (I, result.toString ())
}
}
Private String [] getStringArray (String columnValue) {
If (columnValue = = null)
Return null
Return columnValue.split (,)
}
}
1.2.2 BaseTypeHandler Abstract Class
When implementing our own TypeHandler, in addition to the original implementation interface mentioned above, Mybatis also provides us with an abstract class BaseTypeHandler that implements the TypeHandler interface. So we can also implement our own TypeHandler by inheriting BaseTypeHandler.
Let's first look at the definition of the BaseTypeHandler class:
Java code
Public abstract class BaseTypeHandler extends TypeReference implements TypeHandler {
Protected Configuration configuration
Public void setConfiguration (Configuration c) {
This.configuration = c
}
Public void setParameter (PreparedStatement ps, int I, T parameter, JdbcType jdbcType) throws SQLException {
If (parameter = = null) {
If (jdbcType = = null) {
Throw new TypeException ("JDBC requires that the JdbcType must be specified for all nullable parameters.")
}
Try {
Ps.setNull (I, jdbcType.TYPE_CODE)
} catch (SQLException e) {
Throw new TypeException ("Error setting null for parameter #" + I + "with JdbcType" + jdbcType + "." +
"Try setting a different JdbcType for this parameter or a different jdbcTypeForNull configuration property." +
"Cause:" + e, e)
}
} else {
SetNonNullParameter (ps, I, parameter, jdbcType)
}
}
Public T getResult (ResultSet rs, String columnName) throws SQLException {
T result = getNullableResult (rs, columnName)
If (rs.wasNull ()) {
Return null
} else {
Return result
}
}
Public T getResult (ResultSet rs, int columnIndex) throws SQLException {
T result = getNullableResult (rs, columnIndex)
If (rs.wasNull ()) {
Return null
} else {
Return result
}
}
Public T getResult (CallableStatement cs, int columnIndex) throws SQLException {
T result = getNullableResult (cs, columnIndex)
If (cs.wasNull ()) {
Return null
} else {
Return result
}
}
Public abstract void setNonNullParameter (PreparedStatement ps, int I, T parameter, JdbcType jdbcType) throws SQLException
Public abstract T getNullableResult (ResultSet rs, String columnName) throws SQLException
Public abstract T getNullableResult (ResultSet rs, int columnIndex) throws SQLException
Public abstract T getNullableResult (CallableStatement cs, int columnIndex) throws SQLException
}
We can see that BaseTypeHandler makes a simple choice for the four methods of the TypeHandler interface, filtering the null values, and abstracting the core values and setting methods for subclasses to implement. Another advantage of using BaseTypeHandler is that it inherits another abstract class called TypeReference, and you can get the original types of generics currently used by TypeHandler through the getRawType () method of TypeReference. This is very good for Mybatis when registering for TypeHandler. Without specifying javaType, Mybatis can use it to get the original type of generics used by the current TypeHandler as the javaType type of the TypeHandler to register when registering TypeHandler, which will be discussed when talking about how Mybatis registers TypeHandler.
When implementing our own TypeHandler by inheriting BaseTypeHandler, our StringArrayTypeHandler should write:
Java code
Public class StringArrayTypeHandler extends BaseTypeHandler {
@ Override
Public String [] getNullableResult (ResultSet rs, String columnName)
Throws SQLException {
Return getStringArray (rs.getString (columnName))
}
@ Override
Public String [] getNullableResult (ResultSet rs, int columnIndex)
Throws SQLException {
Return this.getStringArray (rs.getString (columnIndex))
}
@ Override
Public String [] getNullableResult (CallableStatement cs, int columnIndex)
Throws SQLException {
Return this.getStringArray (cs.getString (columnIndex))
}
@ Override
Public void setNonNullParameter (PreparedStatement ps, int I
String [] parameter, JdbcType jdbcType) throws SQLException {
/ / since the case where parameter is null has been dealt with in BaseTypeHandler, we no longer need to judge whether parameter is empty or not, we can just use it.
StringBuffer result = new StringBuffer ()
For (String value: parameter)
Result.append (value) .append (",")
Result.deleteCharAt (result.length () 1)
Ps.setString (I, result.toString ())
}
Private String [] getStringArray (String columnValue) {
If (columnValue = = null)
Return null
Return columnValue.split (,)
}
}
1.3 sign up for TypeHandler
Once you have established your own TypeHandler, you need to register it in Mybatis's configuration file so that Mybatis can recognize and use it. There are two main ways to register TypeHandler, one is by defining the child element typeHandler of the typeHandlers element in the Mybatis configuration file, and the other is by defining the child element package of the typeHandlers element in the Mybatis configuration file. When registering with the typeHandler child element, only one TypeHandler can be registered at a time, while when registering with the package child element, Mybatis registers all the TypeHandler in the specified package as TypeHandler. When registering with the typeHandler child element, we need to indicate the full name of the current TypeHandler to be registered through its handler attribute, which is required. There are two additional attributes that can be specified, one is javaType to specify the corresponding java type, and the other is jdbcType to specify the corresponding jdbc type. When registering with the package child element, we need to specify the package to be scanned through its name attribute, and if we also need to specify the javaType and jdbcType corresponding to the TypeHandler, we need to use annotations on the TypeHandler class to define it. The most basic way for Mybatis to register TypeHandler is to establish a correspondence between javaType, jdbcType, and TypeHandler. When registering with the typeHandler child element, there are three types of registration methods:
1. If we specify javaType and jdbcType, then Mybatis registers a TypeHandler corresponding to javaType and jdbcType.
two。 If we only specify the javaType attribute, there are two cases at this time:
(1) if we specify the corresponding jdbcType with @ MappedJdbcTypes on the TypeHandler class in the form of annotations, Mybatis will register the specified combination of javaType, jdbcType and TypeHandler one by one, including the case where jdbcType is specified as null using this form. Now suppose we have a StringArrayTypeHandler like this:
Java code
@ MappedJdbcTypes ({JdbcType.VARCHAR})
Public class StringArrayTypeHandler implements TypeHandler {
/ /.. The implementation code in the middle is omitted
/ /..
}
Then we register it in the configuration file of Mybatis as follows:
Xml code
Then Mybatis registers StringArrayTypeHandler with javaType as the String array and jdbcType as VARCHAR when actually registering.
(2) if the @ MappedJdbcTypes annotation is not used to specify the corresponding jdbcType, then Mybatis will set jdbcType to null and register a combination of javaType, null and TypeHandler.
3. Neither the javaType attribute nor the jdbcType attribute is specified, or only the jdbcType attribute is specified. There are three types of this situation:
(1) if the corresponding javaType is specified with the annotation @ MappedTypes on the TypeHandler class, then Mybatis will use the corresponding javaType and TypeHandler one by one to register as 2. Now suppose we define a StringArrayTypeHandler like this:
Java code
@ MappedTypes ({String [] .class})
@ MappedJdbcTypes ({JdbcType.VARCHAR})
Public class StringArrayTypeHandler implements TypeHandler {
}
Then, when you register it in Mybatis's configuration file, you specify neither its javaType property nor its jdbcType property, as follows:
Xml code
At this time, when registering the StringArrayTypeHandler, Mybatis will first determine whether it is marked @ MappedTypes, if so, take out its MappedTypes one by one as a javaType, and then register in mode 2. So what Mybatis actually registers here is that javaType is a String array and jdbcType is a combined TypeHandler like VARCHAR.
(2) if the corresponding javaType is not specified with @ MappedTypes on the TypeHandler class, if the current TypeHandler inherits the TypeReference abstract class, Mybatis will use the getRawType () method of TypeReference to get the corresponding javaType type of the current TypeHandler generics, and then use the obtained javaType and TypeHandler to register in mode 2, including a javaType registration for null in mode 2. TypeReference is an abstract class defined in Mybatis, which is mainly used to get the corresponding generic type.
(3) the TypeHandler class is neither marked with @ MappedTypes nor inherited from the TypeReference abstract class. In this case, Mybatis registers the TypeHandler with a combination of null and null.
TypeHandler registered with the package child element will be registered in the manner 3 above.
Here we register our TypeHandler as follows:
Xml code
Notice that the full class name of the String array is "[Ljava.lang.String;", so the javaType property defined above when registering StringArrayTypeHandler is "[Ljava.lang.String;".
1.4 Mybatis automatically acquires TypeHandler
After introducing how Mybatis registers TypeHandler, let's talk about how Mybatis gets the corresponding TypeHandler for type conversion.
If we specify the javaType and jdbcType corresponding to an attribute or variable when configuring the mapping relationship of an attribute or variable in the Mapper.xml file, then Mybatis will find the corresponding TypeHandler of the combination of javaType and jdbcType from the registered TypeHandler for processing, which is also the most basic way for Mybatis to obtain TypeHandler for type conversion. Suppose there is a piece of registration information for TypeHandler in the Mybatis configuration file:
Xml code
Look at a UserMapper.xml definition like this:
Xml code
Insert into t_user (name, age, interests) values (# {name}, # {age}, # {interests, javaType= [Ljava.lang.String;, jdbcType=VARCHAR})
Update t_user set name=# {name}, age=# {age}, interests=# {interests} where id=# {id}
Select * from t_user where id=# {id}
Delete from t_user where id=# {id}
We can see that in the resultMap where id is UserResult, we define a mapping relationship for the corresponding field interests, and define its javaType as "[Ljava.lang.String;" and jdbcType as VARCHAR. At this time, Mybatis will find a TypeHandler in the registered TypeHandler that can handle the type conversion corresponding to javaType and jdbcType for processing. You will find our registered StringArrayTypeHandler here. In the above insert statement with id as insertUser, we also specify its javaType and jdbcType attributes for the variable interests, so Mybatis will also look for the TypeHandler corresponding to javaType and jdbcType. The above definition is the most basic and complete way for Mybatis to get the corresponding TypeHandler. Here, let's do a test on the findById of UserMapper (I won't post its code, anyone with Mybatis foundation should know its code):
Java code
@ Test
Public void testFind () {
SqlSession sqlSession = sqlSessionFactory.openSession ()
Try {
UserMapper userMapper = sqlSession.getMapper (UserMapper.class)
User user = userMapper.findById (20)
System.out.println (user)
} finally {
SqlSession.close ()
}
}
The output is as follows:
Text code
User [age=30, id=20, interests= [Music, Movie, NBA], name= Zhang San]
We can see that Mybatis has converted our field interests of type VARCHAR in the database to an interests property of type User string array type, which means that the StringArrayTypeHandler we defined is working.
In addition to the above fully specified a variable corresponding to the javaType and jdbcType, so that Mybatis can perfectly find the corresponding TypeHandler. We may have the following ways to use it:
1. Only the javaType type corresponding to the variable is specified. At this time, Mybatis will take the combination of javaType and jdbcType for null to look for the corresponding TypeHandler in the registered TypeHandler. Here we also do a test:
(1) without changing the registration information of StringArrayTypeHandler, change our UserMapper.xml to the following form:
Xml code
Select * from t_user where id=# {id}
Run the above test program again at this time, and the output is as follows:
Text code
User [age=30, id=20, interests=null, name= Zhang San]
We can see that the output interests is null, which means that Mybatis does not use the StringArrayTypeHandler we defined to transform interests.
(2) UserMapper.xml is also defined as above, but only specify the javaType attribute to register our StringArrayTypeHandler. The code is as follows:
Xml code
Run the above test code at this time, and the output is as follows:
Text code
User [age=30, id=20, interests= [Music, Movie, NBA], name= Zhang San]
This is because we register the StringArrayTypeHandler with javaType and null, and then look for it with the same javaType and null when we need to convert interests, so we will find our registered StringArrayTypeHandler for type conversion.
two。 Only the jdbcType type corresponding to the variable is specified. At this time, Mybatis will use our specified return type and corresponding attribute to take the corresponding javaType in the return type, and then take the javaType and our specified jdbcType to the registered TypeHandler to get the corresponding TypeHandler. Here we look at a test like this:
Register StringArrayTypeHandler the way you specified javaType and jdbcType before, and then specify jdbcType instead of javaType when defining the interests variable. At this time, the UserMapper.xml is as follows:
Xml code
Select * from t_user where id=# {id}
At this point, continue to run the above test code, and the output is as follows:
Text code
User [age=30, id=20, interests= [Music, Movie, NBA], name= Zhang San]
At this time, Mybatis obtains TypeHandler like this: first, it finds that our interests does not specify javaType. At this time, it will obtain the java type corresponding to the interests attribute of User class, that is, String array, through our specified type User and attribute interests, and then take the acquired javaType and our specified jdbcType, that is, VARCHAR, to find the corresponding TypeHandler. At this time, it will find the StringArrayTypeHandler that we registered with String array and VARCHAR to deal with the type conversion of interests.
Neither the 3.javaType type nor the jdbcType type is specified. At this point, Mybatis will get the corresponding javaType type in mode 2, and then get the corresponding TypeHandler in mode 1. Here we also do a test:
(1) first, register an array whose javaType is String. If jdbcType is not specified, it is the TypeHandler-StringArrayTypeHandler of null. The code is as follows:
Xml code
(2) then, neither javaType nor jdbcType is specified when defining the mapping relationship of our interests field, as follows:
Xml code
Select * from t_user where id=# {id}
Run the above test code again at this time, and the output is as follows:
Text code
User [age=30, id=20, interests= [Music, Movie, NBA], name= Zhang San]
This situation goes like this: we register a StringArrayTypeHandler with javaType for the String array and jdbcType for the null, and then we do not specify the corresponding javaType and jdbcType when defining the mapping of the interests field. At this time, Mybatis will use our specified User type and interests attribute to get the java type corresponding to the interests attribute of the User class, that is, the String array, and then combine jdbcType to find the registered TypeHandler for null, so we find StringArrayTypeHandler. After StringArrayTypeHandler processing, the data from jdbcType to VARCHAR is converted into data from javaType to String array, so the output is shown above.
4. Another form is that we specify the corresponding TypeHandler directly through the variable's typeHandler attribute. In this case, the Mybatis will use the TypeHandler specified by the user for type conversion, instead of obtaining the corresponding TypeHandler by combining javaType and jdbcType. Here we also do a test:
(1) first, register a StringArrayTypeHandler in the configuration file of Mybatis in the way of matching javaType and jdbcType. The code is as follows:
Xml code
As mentioned earlier, if Mybatis fetches the corresponding TypeHandler according to the javaType and jdbcType of the variable, the registered StringArrayTypeHandler can only be obtained if the javaType of the specified variable is a string array and jdbcType is VARCHAR.
(2) then we do not specify the javaType and jdbcType corresponding to the interests field in the UserMapper.xml file, but use the typeHandler attribute to specify that the StringArrayTypeHandler will be used for type conversion, as follows:
Xml code
Select * from t_user where id=# {id}
Run the above test code and output the results:
Text code
User [age=30, id=20, interests= [Music, Movie, NBA], name= Zhang San]
This is because we specify that StringArrayTypeHandler is used for type conversion when mapping interests fields. When you specify the TypeHandler used by a field or variable for mapping, Mybatis uses the given TypeHandler for type conversion when it is needed, instead of looking for the corresponding TypeHandler in the registered TypeHandler through the combination of javaType and jdbcType.
Automatic registration of TypeHandler in 1.5 Mybatis
For some common types of automatic conversion Mybatis has established the relevant TypeHandler for us, and will automatically register them, which mainly include:
Java code
Register (Boolean.class, new BooleanTypeHandler ())
Register (boolean.class, new BooleanTypeHandler ())
Register (Byte.class, new ByteTypeHandler ())
Register (byte.class, new ByteTypeHandler ())
Register (Short.class, new ShortTypeHandler ())
Register (short.class, new ShortTypeHandler ())
Register (Integer.class, new IntegerTypeHandler ())
Register (int.class, new IntegerTypeHandler ())
Register (Long.class, new LongTypeHandler ())
Register (long.class, new LongTypeHandler ())
Register (Float.class, new FloatTypeHandler ())
Register (float.class, new FloatTypeHandler ())
Register (Double.class, new DoubleTypeHandler ())
Register (double.class, new DoubleTypeHandler ())
Register (String.class, new StringTypeHandler ())
Register (String.class, JdbcType.CHAR, new StringTypeHandler ())
Register (String.class, JdbcType.CLOB, new ClobTypeHandler ())
Register (String.class, JdbcType.VARCHAR, new StringTypeHandler ())
Register (String.class, JdbcType.LONGVARCHAR, new ClobTypeHandler ())
Register (String.class, JdbcType.NVARCHAR, new NStringTypeHandler ())
Register (String.class, JdbcType.NCHAR, new NStringTypeHandler ())
Register (String.class, JdbcType.NCLOB, new NClobTypeHandler ())
Register (Object.class, JdbcType.ARRAY, new ArrayTypeHandler ())
Register (BigInteger.class, new BigIntegerTypeHandler ())
Register (BigDecimal.class, new BigDecimalTypeHandler ())
Register (Byte [] .class, new ByteObjectArrayTypeHandler ())
Register (Byte [] .class, JdbcType.BLOB, new BlobByteObjectArrayTypeHandler ())
Register (Byte [] .class, JdbcType.LONGVARBINARY, new BlobByteObjectArrayTypeHandler ())
Register (byte [] .class, new ByteArrayTypeHandler ())
Register (byte [] .class, JdbcType.BLOB, new BlobTypeHandler ())
Register (byte [] .class, JdbcType.LONGVARBINARY, new BlobTypeHandler ())
Register (Object.class, UNKNOWN_TYPE_HANDLER)
Register (Object.class, JdbcType.OTHER, UNKNOWN_TYPE_HANDLER)
Register (Date.class, new DateTypeHandler ())
Register (Date.class, JdbcType.DATE, new DateOnlyTypeHandler ())
Register (Date.class, JdbcType.TIME, new TimeOnlyTypeHandler ())
Register (java.sql.Date.class, new SqlDateTypeHandler ())
Register (java.sql.Time.class, new SqlTimeTypeHandler ())
Register (java.sql.Timestamp.class, new SqlTimestampTypeHandler ())
Register (Character.class, new CharacterTypeHandler ())
Register (char.class, new CharacterTypeHandler ())
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.