Typehandler for a List of a user-defined class

31 views
Skip to first unread message

david Lu

unread,
May 14, 2019, 10:50:01 AM5/14/19
to mybatis-user
I have a entity class like :

    
class Student{
    int id;
    int age;
    List<Course> courseList;
    
    
    static class Course{
        String name;
        String code;
        ...
    }
}

I want to make a type handler for courseList, how can I do? Thanks!

Guy Rouillier

unread,
May 14, 2019, 10:55:42 PM5/14/19
to mybati...@googlegroups.com
All your properties are native types.  You do not need a TypeHandler for native types, as MyBatis already handles them automatically.  And MyBatis also handles List automatically.

What makes you believe you need a TypeHandler?

--
Guy Rouillier
--
You received this message because you are subscribed to the Google Groups "mybatis-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mybatis-user...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/mybatis-user/acafb759-0aae-402d-8cea-2e5a3bab7b4c%40googlegroups.com.

david Lu

unread,
May 15, 2019, 4:52:55 AM5/15/19
to mybati...@googlegroups.com
courseList is stored as a json in t_student table, how can typehandler deal with it?

Guy Rouillier

unread,
May 16, 2019, 2:36:57 AM5/16/19
to mybati...@googlegroups.com
Hmm, that seems like a strange choice for storing the Course data.  Course data contains simple native data types - two string values.  I would think you'd want to normalize this and store in a separate relation.  The Student data is stored in a regular table with separate columns for ID and AGE, but then the courseList is stored as JSON in a single COURSELIST column in JSON format?But perhaps the database was defined by someone else and you have no say in it?

Regardless, sure, you can define a TypeHandler.  The value coming from the database would be a JSON string, and you would translate into Course objects.  Going into the database, you'd start with Course objects, and translate them into a JSON string.

--
Guy Rouillier

david Lu

unread,
May 16, 2019, 4:33:47 AM5/16/19
to mybati...@googlegroups.com
I use student-course just for better explanation, there is no need to create a table for "course" in the project. 

The thing is how to define such a Typehandler? I defined a ListHandler as below, but it can't get the class "Course" and use LinkedMap for deserialization/serialization. 


class ListHandler<T> extends BaseTypeHandler<List<T>> {
private Class<T> clazz
private TypeReference<List<T>> typeRef

ListTypeHandler(Class<T> clazz) {
this.clazz = clazz
this.typeRef = new TypeReference<List<T>>() {}
}

@Override
void setNonNullParameter(PreparedStatement ps, int i, List<T> parameter, JdbcType jdbcType) throws SQLException {
String json = JsonUtil.toString(parameter)
ps.setString(i, json)
}

@Override
List<T> getNullableResult(ResultSet rs, String columnName) throws SQLException {
return parseArray(rs.getString(columnName))
}

@Override
List<T> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
return parseArray(rs.getString(columnIndex))
}

@Override
List<T> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
return parseArray(cs.getString(columnIndex))
}

private List<T> parseArray(String jsonStr) {
return JsonUtil.parseArray(jsonStr, typeRef)
}
}

Iwao AVE!

unread,
May 19, 2019, 12:48:49 PM5/19/19
to mybatis-user

Hi David,

I’m not sure how your JsonUtil works, but to receive Class in a type handler constructor, you may need to specify javaType in the result map.

<resultMap id="studentRM" type="pkg.Student">
  <id column="id" property="id" />
  <result column="age" property="age" />
  <result column="courseList" property="courseList"
    javaType="pkg.Course" typeHandler="pkg.ListHandler" />

Regards,
Iwao


david Lu

unread,
May 20, 2019, 12:34:00 AM5/20/19
to mybati...@googlegroups.com
wow, this may be the solution. But since Course is a static inner class, the compilation failed saying that it can't find the class, so it means mybatis is not able to deal with static inner class?

also, how about the JDBCType?

Guy Rouillier

unread,
May 20, 2019, 2:26:00 AM5/20/19
to mybati...@googlegroups.com
No, it means the syntax used to reference the static nested class is incorrect:


The JDBCType I'm assuming is just VARCHAR, but you haven't shown us your table definition.

--
Guy Rouillier

david Lu

unread,
May 20, 2019, 2:57:57 AM5/20/19
to mybati...@googlegroups.com
I tried by adding javaType, but it doesn't work coz the generic Type T can't be inferred as Course, have you tried it? 

On Mon, May 20, 2019 at 12:48 AM Iwao AVE! <hara...@gmail.com> wrote:

Iwao AVE!

unread,
May 20, 2019, 9:38:50 AM5/20/19
to mybatis-user

Just be sure to use $ when referencing inner classes in MyBatis.
e.g. javaType="pkg.Student$Course"

the generic Type T can’t be inferred as Course, have you tried it?

That is not a MyBatis issue anymore. :)
If you need further assistance, please show us the JsonUtil implementation (or a link to it).
Class seems to be enough, but if JsonUtil requires TypeReference (whatever that is), you are supposed to create a subclass of ListHandler (i.e. extends ListHandler<Cource>), probably.

Regards,
Iwao

Reply all
Reply to author
Forward
0 new messages