如何为EnumSet编写jOOQ转换器(MySQL SET类型)

时间:2015-10-22 08:58:39

标签: java mysql generics enums jooq

我希望将MySQL类型SET与jOOQ代码生成一起使用,简而言之,它类似于MySQL ENUM但具有多个值。

我已尝试但我认为泛型类型擦除会阻止当前Converter实现。也许使用ConverterType的某些TypeToken可以解决问题。类似于it's used on the Gson library

让我们使用这个示例数据库:

CREATE TABLE sometable (
  id int(11) NOT NULL PRIMARY_KEY AUTO_INCREMENT,
  availability set('MONDAY','TUESDAY','WEDNESDAY','THURSDAY','FRIDAY','SATURDAY','SUNDAY')
    COLLATE utf8_spanish_ci NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_spanish_ci;

代码生成器XML可以是这个:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<configuration>
    <!-- Configure the database connection here -->
    <jdbc>
        <driver>org.gjt.mm.mysql.Driver</driver>
        <url>jdbc:mysql://192.168.1.x/test</url>
        <user>xxxx</user>
        <password>xxxx</password>
    </jdbc>
    <generator>
        <database>
            <name>org.jooq.util.mysql.MySQLDatabase</name>
            <inputSchema>test</inputSchema>
            <customTypes>
                <customType>
                    <name>DayOfWeek</name>
                    <type>java.time.DayOfWeek</type>
                    <converter>sargue.DayOfWeekConverter</converter>
                </customType>
            </customTypes>
            <forcedTypes>
                <forcedType>
                    <name>DayOfWeek</name>
                    <expression>day</expression>
                </forcedType>
            </forcedTypes>
        </database>
        <generate>
            <deprecated>false</deprecated>
        </generate>
        <target>
            <packageName>jooq</packageName>
            <directory>src/main/java</directory>
        </target>
    </generator>
</configuration>

所以现在我需要一个转换器。

package sargue;

import org.jooq.Converter;

import java.time.DayOfWeek;
import java.util.EnumSet;

public class DayOfWeekConverter implements Converter<String, EnumSet<DayOfWeek>>{
    @Override
    public EnumSet<DayOfWeek> from(String databaseObject) {
        if (databaseObject == null) return null;
        EnumSet<DayOfWeek> enumSet = EnumSet.noneOf(DayOfWeek.class);
        for (String s : databaseObject.split(","))
            if (!s.isEmpty())
                enumSet.add(DayOfWeek.valueOf(s));
        return enumSet;
    }

    @Override
    public String to(EnumSet<DayOfWeek> userObject) {
        if (userObject == null) return null;
        return userObject.stream().map(Enum::toString).collect(Collectors.joining(","));
    }

    @Override
    public Class<String> fromType() {
        return String.class;
    }

    @Override
    public Class<EnumSet<DayOfWeek>> toType() {
        // This doesn't work... we need something to circunvent type erasure
        // some sort of TypeToken as in other libraries
        return new EnumSet<DayOfWeek>().getClass();
    }
}

我想我可以为EnumSet编写一个转换器,但是我会丢失封闭的类型,所以它没用。或者也许我错了,可以做到!

可以吗?

1 个答案:

答案 0 :(得分:1)

这是一个好主意。我怀疑在未来的jOOQ中添加此功能是值得的:#4694

通过这两项修复,您应该能够实现您正在寻找的内容:

XML配置

<customType>
    <name>DayOfWeek</name>
    <type>java.util.EnumSet&lt;java.time.DayOfWeek&gt;</type>
    <converter>sargue.DayOfWeekConverter</converter>
</customType>

转换器代码

@SuppressWarnings({"unchecked", "rawtypes"})
@Override
public Class<EnumSet<DayOfWeek>> toType() {
    return (Class) EnumSet.class;
}

没有其他方法可以创建Class<EnumSet<DayOfWeek>>DayOfWeek对象中丢失了Class类型信息。 See also this question here。有一些技巧,比如你提到的那些,但你真的不需要应用任何这些技巧。