我们知道, Java 和 MySQL 中的数据类型是不同的, Java 中除了基本数据类型, 还有对象.
有时候使用 MySQL 存储数据, 或者从 MySQL 中读取数据时, 会有一些特殊需求 ?? , 比如:
将 Integer 数组直接存入 MySQL, 保存为 BLOB 形式, 读取出来时又是正常的 Integer 数组
将 Integer 数组转换为 String, 然后存入 MySQL, 使用 varchar 类型, 读取出来时又是正常的 Integer 数组
这也太难了叭!
解决办法有两种:
Basic Method:Java 在存入数据之前, 或读取数据之后, 做手动类型转换
Clever Method: 定义 TypeHandler, 并在 Mybatis 对应位置指明
关于第一种方法这里不予赘述, 不够 Smart. 这里主要讲述如何自定义 Handler, 来解决 Java 数据 ->MySQL 数据的特殊类型转换问题??
这种 Handler 不仅方便了我们的数据库操作, 还有利于代码的复用.
这里以 Integer[] 数组的存储为形如, 1,2,3, 的 varchar 字符串为例.
问题示例
我们定义一个 role 类, 与数据库的 role 表对应:
- public class Role {
- private Integer id;
- private String name;
- private Integer[] accessIds;
- private Date createTime;
- // ... ignore get and set methods
- }
注意到里面有一个 accessIds 字段, 它的类型是 Integer[]
数据库设计:
- DROP TABLE IF EXISTS `role`;
- CREATE TABLE `role` (
- `id` int(11) NOT NULL AUTO_INCREMENT,
- `name` varchar(255) NOT NULL,
- `access_ids` varchar(255) DEFAULT NULL,
- `create_time` datetime NOT NULL,
- PRIMARY KEY (`id`)
- ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
- -- ----------------------------
- -- Records of role
- -- ----------------------------
- INSERT INTO `role` VALUES ('1', '测试角色', ',1,2,', '2019-11-14 13:43:14');
自定义 Handler 类
通过继承 BaseTypeHandler 类, 重写其方法, 定义一个 Integer[] 与数据库 varchar 类型自动转换的 Handler 类:
- /**
- * Java Int 数组与 MySQL String 转换器
- * 比如 [1,2,3] --> ",1,2,3,"
- */
- public class StringToIntArrayHandler extends BaseTypeHandler<Integer[]> {
- private static final String splitCharset = ",";
- @Override
- public void setNonNullParameter(PreparedStatement ps, int i, Integer[] objects, JdbcType jdbcType) throws SQLException {
- String str = arrayToString(objects);
- ps.setString(i, str);
- }
- @Override
- public Integer[] getNullableResult(ResultSet rs, String columnName) throws SQLException {
- String str = rs.getString(columnName);
- return stringToArray(str);
- }
- @Override
- public Integer[] getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
- String str = rs.getString(columnIndex);
- return stringToArray(str);
- }
- @Override
- public Integer[] getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
- String str = cs.getString(columnIndex);
- return stringToArray(str);
- }
- // --- private methods ---
- /**
- * Integer 数组转 String
- * 注: 使用提前设定好的分隔符分割数组的每一项
- */
- private static String arrayToString(Integer[] array) {
- StringBuilder res = new StringBuilder();
- if (array != null && array.length> 0) {
- for (Object o : array) {
- res.append(splitCharset).append(o.toString());
- }
- res.append(splitCharset);
- }
- return res.length()> 0 ? res.toString() : null;
- }
- /**
- * 从 String 转 Integer 数组
- * 注: String 是用分隔符分割的, 使用 String.split 方法可以分解为数组
- */
- private static Integer[] stringToArray(String str) {
- List<Integer> list = new ArrayList<>();
- if (str != null) {
- String[] array = str.split(splitCharset);
- if (array.length> 0) {
- for (String o : array) {
- if (o != null && o.length()> 0) {
- list.add(Integer.parseInt(o));
- }
- }
- }
- }
- return list.toArray(new Integer[0]);
- }
- }
这个类的具体作用是什么呢?
当 Java 中类型是 Integer[] 时, 使用这个 Handler 类, 将 Integer[] 转换为以, 号分割的字符串, 然后存入数据库
当从数据库读取以, 分割值的字符串时, 可以通过这个 Handler, 自动将字符串转换为 Integer[] 数组
下面我们演示一下具体的使用??
在 Mybatis 中应用自定义的 Handler
Mybatis 存放 SQL 语句的 xml 文件??:
- <?xml version="1.0" encoding="UTF-8" ?>
- namespace="com.example.model.dao.RoleDAO">
- id="roleMap" type="com.example.model.bean.Role">
- property="id" column="id"/>
- property="name" column="name"/>
- property="accessIds" column="access_ids"
- typeHandler="ccom.example.model.dao.handler.StringToIntArrayHandler"/>
- property="createTime" column="create_time"/>
- id="findById" parameterType="map" resultMap="roleMap">
- SELECT id, name, access_ids, create_time
- FROM role
- WHERE id = #{id}
- id="insert" parameterType="com.example.model.bean.Role">
- resultType="java.lang.Integer" order="AFTER" keyProperty="id">
- SELECT LAST_INSERT_ID()
- INSERT INTO role
- (name, create_time, access_ids)
- VALUES
- (#{name}, #{createTime}
- , #{accessIds, jdbcType=VARCHAR, typeHandler=com.example.model.dao.handler.StringToIntArrayHandler})
以上 xml 中演示了 select 和 insert 两种情况时, 如何应用 typeHandler.
来源: http://www.bubuko.com/infodetail-3287976.html