QueryDsl and hibernate CompositeUserType

323 views
Skip to first unread message

Damien Hollis

unread,
Mar 27, 2014, 10:15:04 PM3/27/14
to quer...@googlegroups.com
Hi,

In our project, we have a Money class and we use a hibernate usertype to persist it to the database.  When I generate Q classes, it does to notice that this class has a usertype and therefore does not generate the correct type.

Here is an example of the code:

public class Money extends Number implements Comparable<Money> {
    private BigDecimal amount;
    private Currency currency;

...
}

public class MoneyUserType implements CompositeUserType, ParameterizedType {

    @NotNull
    private final int[] sqlTypes;

    @NotNull
    private final String[] propertyNames = {"amount", "currencyCode"};

    @NotNull
    private final Type[] propertyTypes = {BIG_DECIMAL, STRING};

    public MoneyUserType() {
        sqlTypes = new int[]{Types.NUMERIC, Types.VARCHAR};
    }

    @NotNull
    public int[] sqlTypes() {
        return sqlTypes;
    }

    @NotNull
    @Override
    public Class<Money> returnedClass() {
        return Money.class;
    }

    @NotNull
    @Override
    public String[] getPropertyNames() {
        return propertyNames;
    }

    @NotNull
    @Override
    public Type[] getPropertyTypes() {
        return propertyTypes;
    }
...
}

And it is mapped using the following:

    @Columns(columns = {
            @Column(name = "AMOUNT", nullable = false, precision = LENGTH_MONEY_PRECISION, scale = LENGTH_MONEY_SCALE),
            @Column(name = "CURRENCY", nullable = false, length = LENGTH_MONEY_CURRENCY)
    })
    @org.hibernate.annotations.Type(type = "MoneyUserType")
    private Money value;

I've done quite a lot of searching but I can't find any examples of how to configure querydsl to support custom usertypes - is it possible?  If not, is there a workaround until the code generation supports these?

Regards,
Damien

timowest

unread,
Mar 28, 2014, 3:36:57 AM3/28/14
to quer...@googlegroups.com
Hi.

Do you mean that no QMoney is generated? Querydsl generates metaclasses by default only for entities, mapped superclasses and embeddables.

Br,
Timo

Damien Hollis

unread,
Mar 28, 2014, 4:46:55 AM3/28/14
to quer...@googlegroups.com
Hi,

Yes, no QMoney type is generated. Can I cause one to be generated?

Regards,
Damien

timowest

unread,
Mar 28, 2014, 9:12:34 AM3/28/14
to quer...@googlegroups.com
Hi.

For now this is not possible. I assume that you want to refer to properties of Money in a query?

Timo

Damien Hollis

unread,
Mar 28, 2014, 2:30:32 PM3/28/14
to quer...@googlegroups.com
Yes, I want to be able to refer to the properties of the Money class - in the particular case I came across I was trying to sum the values. Ideally I would also be able to use the money as a parameter and have querydsl or hibernate break it into its parts for the query (I think hibernate already does this) - but this is a nice to have as I can simulate this with a helper method.

Do you think you will have support for this anytime soon?

Regards,
Damien

timowest

unread,
Mar 28, 2014, 3:09:20 PM3/28/14
to quer...@googlegroups.com
Hi Damien.

I will try figure out a way to do it and get back to you.

Timo

Dingo

unread,
Mar 29, 2014, 9:47:30 AM3/29/14
to quer...@googlegroups.com
Outside of the Querydsl questions more to the money support there are existing libraries that provide these ; I'm currently using jodamoney and Jadira but looking at the new JSR working group version too http://javamoney.github.io/.

timowest

unread,
Mar 30, 2014, 2:20:05 PM3/30/14
to quer...@googlegroups.com
Hi Damien.

I think the best option for now is to use querydsl.unknownAsEmbeddable=true APT option as documented here http://www.querydsl.com/static/querydsl/3.3.2/reference/html/ch03s03.html

This will enable metaclass creation for referenced non-annotated classes.

Br,
Timo

Damien Hollis

unread,
Mar 30, 2014, 4:13:57 PM3/30/14
to quer...@googlegroups.com
Hi Dingo,

Thanks for the information.  We started our project quite a while ago before those projects existed, so we have a lot of code that already uses our Money implementation and therefore it isn't, currently, feasible to change.  But we'll keep an eye on those projects and consider them in the future.

Cheers,
Damien

Damien Hollis

unread,
Mar 30, 2014, 4:22:44 PM3/30/14
to quer...@googlegroups.com
Hi Timo,

I enabled that option but it caused the annotation processor to error:

    [javac] An annotation processor threw an uncaught exception.
    [javac] Consult the following stack trace for details.
    [javac] java.lang.NullPointerException
    [javac]     at com.mysema.query.codegen.TypeResolver.resolveVar(TypeResolver
.java:85)
    [javac]     at com.mysema.query.codegen.TypeResolver.resolve(TypeResolver.ja
va:44)
    [javac]     at com.mysema.query.codegen.Property.createCopy(Property.java:83
)
    [javac]     at com.mysema.query.codegen.EntityType.include(EntityType.java:2
26)
    [javac]     at com.mysema.query.apt.AbstractQuerydslProcessor.addSupertypeFi
elds(AbstractQuerydslProcessor.java:438)
    [javac]     at com.mysema.query.apt.AbstractQuerydslProcessor.processAnnotat
ions(AbstractQuerydslProcessor.java:189)
    [javac]     at com.mysema.query.apt.AbstractQuerydslProcessor.process(Abstra
ctQuerydslProcessor.java:122)
    [javac]     at com.sun.tools.javac.processing.JavacProcessingEnvironment.cal
lProcessor(JavacProcessingEnvironment.java:793)
    [javac]     at com.sun.tools.javac.processing.JavacProcessingEnvironment.dis
coverAndRunProcs(JavacProcessingEnvironment.java:722)
    [javac]     at com.sun.tools.javac.processing.JavacProcessingEnvironment.acc
ess$1700(JavacProcessingEnvironment.java:97)
    [javac]     at com.sun.tools.javac.processing.JavacProcessingEnvironment$Rou
nd.run(JavacProcessingEnvironment.java:1029)
    [javac]     at com.sun.tools.javac.processing.JavacProcessingEnvironment.doP
rocessing(JavacProcessingEnvironment.java:1163)
    [javac]     at com.sun.tools.javac.main.JavaCompiler.processAnnotations(Java
Compiler.java:1108)
    [javac]     at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.ja
va:824)
    [javac]     at com.sun.tools.javac.main.Main.compile(Main.java:439)
    [javac]     at com.sun.tools.javac.main.Main.compile(Main.java:353)
    [javac]     at com.sun.tools.javac.main.Main.compile(Main.java:342)
    [javac]     at com.sun.tools.javac.main.Main.compile(Main.java:333)
    [javac]     at com.sun.tools.javac.Main.compile(Main.java:76)
    [javac]     at com.sun.tools.javac.Main.main(Main.java:61)

I put a breakpoint on the TypeResolver line 85 and the first time it hits that breakpoint I have an interface that has two supertypes - which means the method getSuperType() returns null.  It seems like with that option enabled, things like interfaces are being considered too (when they probably shouldn't be).  

Regards,
Damien

timowest

unread,
Mar 31, 2014, 2:23:50 AM3/31/14
to quer...@googlegroups.com
Hi.

Ok. I will look into this exception later.

For now you can use the QueryEntities annotation on the package level (package-info.java) and add your Money type via it.

@QueryEntities(Money.class)

Timo

Damien Hollis

unread,
Mar 31, 2014, 4:47:11 AM3/31/14
to quer...@googlegroups.com
Hi Timo,

That works and personally I think it is better than generating Q types for all unknown classes.  So I'm happy to stick with this as a solution for now.  If you manage to add support for UserTypes, let me know and I'll be happy to test.

Thanks,
Damien
Reply all
Reply to author
Forward
0 new messages