Reputation: 5875
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
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:
<customType>
<name>DayOfWeek</name>
<type>java.util.EnumSet<java.time.DayOfWeek></type>
<converter>sargue.DayOfWeekConverter</converter>
</customType>
@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