Issue
I'm trying to use the jOOQ fetchInto()
method to map to an existing Hibernate model Organization
(class and its inheritances are below).
Organization organization = jooq().select().from(ORGANIZATION).fetchOne().into(Organization.class);
The problem I have is that I can't really understand what happens in DefaultRecordMapper as I feel I'm not entirely familiar with all the terms that are used. I'm trying to figure out how it applies to the Hibernate classes that are in my codebase.
So far what I've tried:
- Use the jOOQ generated POJO's to see if it retrieves and maps the data at all (works).
- Add a constructor, getters and setters to the
Organization
Hibernate model. - Add
@Column
annotation toname
in theOrganization
Hibernate model.
What works:
id
field gets mapped correctly.
What doesn't work:
name
field doesn't get mapped (null
).createdAt
andmodifiedAt
fields do not get mapped (null
).
My question is: Is there something I am overlooking with the mapping and what are the things I should look at concerning the classes, fields, constructors and annotations with Hibernate models? I want to eventually map all the Hibernate models in the codebase and use fetchInto
to do that.
Thanks! :)
@Entity
public class Organization extends BaseModel {
@Required public String name;
//... a lot of other code
}
@MappedSuperclass
public class BaseModel extends Model {
/** The datetime this entity was first saved. Automatically set by a JPA prePersist */
@NoBinding
@Column
@Type(type = "org.jadira.usertype.dateandtime.joda.PersistentDateTime")
public DateTime createdAt;
/** The datetime this entity was last modified. Automatically set by a JPA preUpdate */
@NoBinding
@Column
@Type(type = "org.jadira.usertype.dateandtime.joda.PersistentDateTime")
public DateTime modifiedAt;
//...
}
@MappedSuperclass
public class Model extends GenericModel { // Both Model and GenericModel are from the Play Framework
@Id
@GeneratedValue
public Long id;
public Model() {
}
public Long getId() {
return this.id;
}
public Object _key() {
return this.getId();
}
}
Solution
jOOQ doesn't support all the many JPA and Hibernate specific annotations. Historically, it supported a few JPA annotations (because why not), but full interop would be excessive and investing product development time in the wrong places. jOOQ is by no means a JPA implementation.
Step 0: Why didn't (some) of the mappings work?
As mentioned before, not all JPA specification is implemented. For example, a known issue is that @Column
annotations are still mandatory in jOOQ:
https://github.com/jOOQ/jOOQ/issues/4586
There might be other such limitations, which could be considered bugs. Feel free to report them if you want to continue down this path: https://github.com/jOOQ/jOOQ/issues/new/choose
But things like @MappedSuperclass
or @Type
are unlikely to ever be supported by jOOQ.
Step 1: Do you really need it?
You've decided to create and run your query with jOOQ. I imagine your actual query is much more complex than what you're showing, because for that particular query, you don't need jOOQ.
Do you really need to map to Hibernate entities? Because even when you use Hibernate, the recommended approach is to use entities only when you're going to modify them and store the delta back to the database. If that's the case, see step 2 below. If it's not the case, why not use jOOQ's own mapping functionality to work with any style of jOOQ supported POJO?
Step 2: Use Hibernate to execute the jOOQ query
If you're using jOOQ only to build a rather complex SQL query and you need Hibernate entities as a result, then use Hibernate to execute the jOOQ query as documented here. A small utility should be enough:
public static <E> List<E> nativeQuery(EntityManager em, org.jooq.Query query, Class<E> type) {
Query result = em.createNativeQuery(query.getSQL(), type);
List<Object> values = query.getBindValues();
for (int i = 0; i < values.size(); i++)
result.setParameter(i + 1, values.get(i));
return result.getResultList();
}
Answered By - Lukas Eder