sargue
sargue

Reputation: 5875

How to write a jOOQ converter for an EnumSet (MySQL SET type)

I want to use the MySQL type SET with jOOQ code generation which, in a nutshell, is like the MySQL ENUM but with multiple values.

I've tried but I think the generics type erasure prevents this with the current Converter implementation. Maybe some ConverterType which uses a TypeToken could solve the problem. Something like it's used on the Gson library.

Let's work with this example database:

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;

And a code generator XML could be this one:

<?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>

So now I need a converter.

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();
    }
}

I think I could write a Converter for an EnumSet but I will lose the enclosed type so it's useless. Or maybe I'm wrong and it can be done!

Can it be done?

Upvotes: 2

Views: 914

Answers (1)

Lukas Eder
Lukas Eder

Reputation: 220842

That's a good idea. I suspect it's worth adding this functionality as a feature in a future jOOQ: #4694

With these two fixes, you should be able to implement what you're looking for:

XML configuration

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

Converter code

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

There's no other way to create a Class<EnumSet<DayOfWeek>>. The DayOfWeek type information is lost in the Class object. See also this question here. There are tricks like the ones you've mentioned, but you don't really need to apply any of those tricks.

Upvotes: 1

Related Questions