我想在jOOQ代码生成中使用MySQL类型SET,简而言之,它类似于MySQLENUM,但有多个值。
我已经尝试过了,但我认为泛型类型擦除在当前的Converter实现中阻止了这种情况。也许一些使用ConverterTypeTypeToken可以解决这个问题。类似于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();
    }
}

我想我可以为一个枚举集编写一个转换器,但是我将丢失封闭的类型,因此它是无用的。或者也许我错了,这是可以做到的!
能做到吗?

最佳答案

这是个好主意。我觉得在未来的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。有些技巧和你提到的一样,但是你不需要运用这些技巧。

10-07 12:20
查看更多