Comments (4)
I think you are running against the limitations of what can be expressed with annotations.
The main problem is that your "MyClass" is parameterized but you use the raw type ("MyClass") in the Sql object. In addition, the @RegisterBeanMapper
annotation does registers a bean mapper for the bean in question but there is no type information on what to do with the "T" that is part of the type definition.
You basically have two options:
a)
have a concrete type for the row. Instead of MyClass<T>
have an MyIntClass extends MyClass<Integer>
that resolves the T
to an Integer (or whatever type you want to use).
Now this works:
@SqlQuery("select m.name as name, m.* from my_table m where condition=:value;")
@KeyColumn("name")
@RegisterConstructorMapper(MyIntClass.class)
Multimap<String, MyIntClass> getIntMap(String value);
Note that Jdbi still needs to know how to construct the Multimap. If this is a Guava multimap, you need to load the Guava plugin.
b) You do not have a concrete type but want to use a generic:
@SqlQuery("select m.name as name, m.* from my_table m where condition=:value;")
@KeyColumn("name")
Multimap<String, MyClass<Integer>> getMap(int id);
Note that you still need to use a concrete type in the method. Java does not have dynamic typing, you need to provide an actual type information.
Also, you can not register the row mapper with an annotation. Same problem. You need to resolve the type (e.g. MyClass<Integer>
) and assign a mapper to it.
So you need to implement the mapper:
public static class MyIntClassMapper implements RowMapper<MyClass<Integer>> {
@Override
public User<Integer> map(ResultSet rs, StatementContext ctx) throws SQLException {
... map columns onto MyClass<Integer> ...
}
}
and register it with Jdbi:
jdbi.registerRowMapper(new GenericType<>() {}, new MyIntClassMapper());
(note that at least with reasonably modern Java (this is with 17) it can resolve the type information for the "GenericType<>" from the mapper parameter).
because all of this is a mouthful, I put a complete example together for you at https://github.com/jdbi/jdbi/pull/2636/files, this will go into the e2e testing module as TestIssue2623
.
from jdbi.
I think you are running against the limitations of what can be expressed with annotations. The main problem is that your "MyClass" is parameterized but you use the raw type ("MyClass") in the Sql object.
As I've mentioned, I've tried all combinations... quote from description:
fails with Map<String, MyClass> or Map<String, MyClass> or MultiMap<String, MyClass> as well.
....
Also, you can not register the row mapper with an annotation. Same problem. You need to resolve the type (e.g.
MyClass<Integer>
) and assign a mapper to it.So you need to implement the mapper:
public static class MyIntClassMapper implements RowMapper<MyClass<Integer>> { @Override public User<Integer> map(ResultSet rs, StatementContext ctx) throws SQLException { ... map columns onto MyClass<Integer> ... } }
We tried this - i.e. adding a custom row mapper and using the class with type provided. It works in code, but when we create a jar out of it (packaging our application), then it fails with the same exception of missing row mapper. We will raise a bug separately for this weird behavior.
and register it with Jdbi:
jdbi.registerRowMapper(new GenericType<>() {}, new MyIntClassMapper());
We did not try this, we registered the row mapper using the annotation itself.
(note that at least with reasonably modern Java (this is with 17) it can resolve the type information for the "GenericType<>" from the mapper parameter).
because all of this is a mouthful, I put a complete example together for you at https://github.com/jdbi/jdbi/pull/2636/files, this will go into the e2e testing module as
TestIssue2623
.
Thanks!
from jdbi.
I think you are running against the limitations of what can be expressed with annotations. The main problem is that your "MyClass" is parameterized but you use the raw type ("MyClass") in the Sql object.
As I've mentioned, I've tried all combinations... quote from description:
fails with Map<String, MyClass> or Map<String, MyClass> or MultiMap<String, MyClass> as well.
As it is expected. MyClass<T>
is a parameterized class (the T
is the parameter). There is no generic mapper for the type T
, it needs to be resolved to a concrete type at some point. Java does not support dynamic typing, so you need to either have a class that extends MyClass<String>
if T
is a string or MyClass<Integer>
if T
is an integer. If you want to use the "any" type, you need to register the mapper for MyClass<Object>
.
Each of your examples is using a "raw" MyClass. Jdbi can not find a row mapper for a "raw" MyClass. That is why it reports the error.
In the example, the jdbi.registerRowMapper(new GenericType<>() {}, new MyIntClassMapper());
stanza actually registers a mapper for a generic MyClass<Integer>
type. Java can infer that type for the first argument from the second, which is why there is just an empty <>
. But what the code actually does is jdbi.registerRowMapper(new GenericType<MyClass<Integer>>() {}, new MyIntClassMapper());
All the behavior of Jdbi is consistent with what you configured. Generics are tricky and omitting the generic type parameter and using a raw type generally does not work.
As I said, there are limitations to what you can do with the annotations. Registering mappers is limited to concrete classes and using the @RegisterBeanMapper
, @RegisterConstructorMapper
or @RegisterFieldMapper
require the mapper type to match the row type.
from jdbi.
For the MultiMap, you need a collector btw. If you use the Guava multimap (https://guava.dev/releases/snapshot-jre/api/docs/com/google/common/collect/Multimap.html), we provide a collector as part of the jdbi3-guava module.
If you use another MultiMap, you need to register a collector with Jdbi, otherwise it can not construct the collection object.
from jdbi.
Related Issues (20)
- Memory consumption for generated SqlObject DAO HOT 4
- @UseFreemarkerSqlLocator is ignored when it comes before @UseFreemarkerEngine HOT 5
- Can not set static final field HOT 4
- DAO/SqlObject interface performance HOT 8
- Investigate libyears HOT 2
- Exceptiona are thrown after tests execution, if the database test container is closed prematurely. HOT 14
- Thread-based nesting behavior for managed handles is surprising and not adequately documented HOT 5
- japicmp chokes when run on a tag
- reproducible build validation for a tag needs to skip japicmp
- createQuery does not throw any error when bind call has incorrect parameter number
- [MSSQL] Snapshot transaction isolation level cannot be used with `inTransaction` methods HOT 1
- [postgres] INSERT and SELECT in one request doesn't work properly HOT 2
- Move Oracle artifact back into main build
- InTransaction does not call transactionHandler.inTransaction when initalAutoCommit=false HOT 4
- How to specify CaseStrategy for MapMapper in SqlObject Extension? HOT 3
- Nested objects doesn't work with inner joins and register bean mapper HOT 6
- OptionalRowMapperFactory can cause NullPointerExceptions with custom Row Mappers HOT 1
- Transaction not work on DAO bean without an attachment. HOT 2
- Accidental one-based arguments fail silently HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from jdbi.