How to map to an existing Hibernate model using jOOQ fetchInto()? - java

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 to name in the Organization Hibernate model.
What works:
id field gets mapped correctly.
What doesn't work:
name field doesn't get mapped (null).
createdAt and modifiedAt 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();
}
}

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

Related

How to check properties with Hibernate efficiently?

We are using Hibernate for Object/Relational Mapping. This works fine when loading entire entities. However, often I face the problem that I simply want to check a single attribute or COUNT() table entries based on a certain criteria. For sake of performance, I use Native SQL in those cases instead of loading several objects from database and checking their properties in Java. But having plain SQL queries is error-prone and I feel like it violates the idea of ORM.
So I wonder, is there any ORM approach to check single attributes with Hibernate efficiently?
Example: Let's assume we have two entity beans Order and OrderPosition. We want to check, if an order is partly delivered (i.e. COUNT(OrderPositions WHERE isDelivered = true) > 0).
#Entity
public class Order {
private long id;
private List<OrderPosition> orderPositions;
// ...
}
#Entity
public class OrderPosition {
private isDelivered = false;
// ...
}
(Code is simplified for readability.)

JPA fetch collection of subclass

I have a case where we have an inheritance strategy like this (this is an example of the jpa wiki, our real example is an other business case :))
#Entity
#Inheritance
#DiscriminatorColumn(name="PROJ_TYPE")
#Table(name="PROJECT")
public abstract class Project {
#Id
private long id;
...
}
#Entity
#DiscriminatorValue("L")
public class LargeProject extends Project {
#OneToMany
private Set<Member> members;
}
#Entity
#DiscriminatorValue("S")
public class SmallProject extends Project {
}
I have a bunch of projects in my database and want to fetch all the projects at once, but by doing this, i also want to fetch my list of members at once.
Is there a way to do this with jpql? I know the TYPE annotation allows me to look at the type, but can I combine this with a JOIN FETCH?
I'm using hibernate, but don't want to downgrade back to the hibernate api if I don't need to
JPA and Hibernate doesn't support fetching associations from subclasses, unless the property is also present in the topmost member of the hierarchy. But according to this post (https://thorben-janssen.com/fetch-association-of-subclass/) you can work around this limitation by exploiting hibernate's level 1 cache mechanism.
In you case you'll fetch all instances of Member first, in a separated query, and then perform your query on Project, letting LargeProject.members to be Lazy loaded. Instead of performing N + 1 SELECTs, hibernate will fetch those from the cache.
A bit late but I found a way by using only JPQL.
In your case :
SELECT p FROM Project p JOIN FETCH ((TREAT(p as LargeProject)).members)

Mapping JSON object to Hibernate entity

I'm going to start a project of a REST application managed with Spring and with Hibernate for my model.
I know that Spring allows you to get Java object from the HTTP Request (with #Consumes(JSON) annotation). Is there any conflict if this Java object is also a Hibernate entities? And is nested object working (like #ManyToOne relation)?
Maven dependency
The first thing you need to do is to set up the following Hibernate Types Maven dependency in your project pom.xml configuration file:
<dependency>
<groupId>com.vladmihalcea</groupId>
<artifactId>hibernate-types-52</artifactId>
<version>${hibernate-types.version}</version>
</dependency>
Domain model
Now, if you are using PostgreSQL, you need to use the JsonType from Hibernate Types.
In order to use it in your entities, you will have to declare it on either class level or in a package-info.java package-level descriptor, like this:
#TypeDef(name = "json", typeClass = JsonType.class)
And, the entity mapping will look like this:
#Type(type = "json")
#Column(columnDefinition = "json")
private Location location;
If you're using Hibernate 5 or later, then the JSON type is registered automatically by the Postgre92Dialect.
Otherwise, you need to register it yourself:
public class PostgreSQLDialect extends PostgreSQL91Dialect {
public PostgreSQL92Dialect() {
super();
this.registerColumnType( Types.JAVA_OBJECT, "json" );
}
}
The JsonType works with Oracle, SQL Server, PostgreSQL, MySQL, and H2 as well. Check out the project page for more details about how you can map JSON column types on various relational database systems.
Yes, this wouldn't be a problem and is actually a fairly common practice.
In the recent years I have come to realize that sometimes, however, it is not a good idea to always build your views based on your domain directly. You can take a look at this post:
http://codebetter.com/jpboodhoo/2007/09/27/screen-bound-dto-s/
It is also known as "Presentation Model":
http://martinfowler.com/eaaDev/PresentationModel.html
The idea behind that is basically the following:
Imagine you have the domain entry User, who looks like that :
#Entity
#Data
public class User {
#Id private UUID userId;
private String username;
#OneToMany private List<Permission> permissions;
}
Let's now imagine you have a view where you wanna display that user's name, and you totally don't care about the permissions. If you use your approach of immediately returning the User to the view, Hibernate will make an additional join from the Permissions table because event though the permissions are lazily loaded by default, there is no easy way to signal to the jackson serializer or whatever you are using, that you don't care about them in this particular occasion, so jackson will try to unproxy them (if your transaction is still alive by the time your object is put for json serialization, otherwise you get a nasty exception). Yes, you can add a #JsonIgnore annotation on the permissions field, but then if you need it in some other view, you are screwed.
That a very basic example, but you should get the idea that sometimes your domain model can't be immediately used to be returned to the presentation layer, due to both code maintainability and performance issues.
We were using such approach to simplify design and get rid of many dtos (we were abusing them too much). Basically, it worked for us.
However, in our REST model we were trying to do not expose other relations for an object as you can always create another REST resources to access them.
So we just put #JsonIgnore annotations to relations mappings like #OneToMany or #ManyToOnemaking them transient.
Another problem I see that if you still like to return these relations you would have to use Join.FETCH strategy for them or move transaction management higher so that transaction still exists when a response is serialized to JSON (Open Session In View Pattern).
On my opinion these two solutions are not so good.
You can map the json request without using any library at REST web-services (Jersy)
this sample of code:
This hibernate entity called book:
#Entity
#Table(name = "book", schema = "cashcall")
public class Book implements java.io.Serializable {
private int id;
private Author author; // another hibernate entity
private String bookName;
//setters and getters
}
This web-services function
#POST
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public String addBook(Book book) {
String bookName=book.getName();
return bookName;
}
This is sample json request:
{
"bookName" : "Head First Java",
"author" : {
"id" : 1
}
}
Since you are just starting, perhaps you could use Spring Data REST?
This is the project: http://projects.spring.io/spring-data-rest/
And here are some simple examples:
https://github.com/spring-projects/spring-data-book/tree/master/rest
https://github.com/olivergierke/spring-restbucks
As you can see in the examples, there are no extra DTOs beyond the #Entity annotated POJOs.

Can Hibernate be used to store HashMaps of data without classes to represent their structure?

I have pretty much zero experience with Hibernate, though I've used similar persistence libraries in other languages before. I'm working on a Java project that will require a way to define "models" (in the MVC sense) in text configuration files, generate the database tables automatically, and (ideally) be database-backend-agnostic. As far as I can tell from some quick Googling, Hibernate is the only widely-used backend-agnostic Java database library; while I could write my own compatibility layer between my model system and multiple DB backends, that's a debugging endeavor that I'd like to avoid if possible.
My question is: Can Hibernate be used to store data whose structure is represented in some other way than an annotated Java class file, such as a HashMap with some configuration object that describes its structure? And, if not, are there any other relatively-stable Java database libraries that could provide this functionality?
EDIT: Here's a clearer description of what I'm trying to accomplish:
I am writing a data-modeling library. When a certain method of the library is called, and passed a configuration object (loaded from a text file), it should create a new "model," and create a database table for that model if necessary. The library can be queried for items of this model, which should return HashMaps containing the models' fields. It should also allow HashMaps to be saved to the database, provided their structure matches the configuration files. None of these models should be represented by actual compiled Java classes.
I think you could try use #MapKey annotation provided by JPA (not the Hibernate #MapKey annotation, it's pretty different!).
#javax.persistence.OneToMany(cascade = CascadeType.ALL)
#javax.persistence.MapKey(name = "name")
private Map<String, Configuration> configurationMap = new HashMap<String, Configuration>();
I don't believe Hibernate will let you have a Map as an #Entity but it will let you have a custom class that contains a map field:
#Entity
public class Customer {
#Id #GeneratedValue public Integer getId() { return id; }
public void setId(Integer id) { this.id = id; }
private Integer id;
#OneToMany #JoinTable(name="Cust_Order")
#MapKeyColumn(name"orders_number")
public Map<String,Order> getOrders() { return orders; }
public void setOrders(Map<String,Order> orders) { this.orders = orders; }
private Map<String,Order> orders;
}
(example from Hibernate docs)
Additionally, you don't have to use annotations (if that is what you're trying to avoid): Hibernate relationships can be described via xml files and there are utilities (maven plugins for example) which can automatically generate the necessary java pojo's from the xml.
Does your model require a relational database? You might consider a database like Mongo that stores any object you can represent with JSON.
you can configure hibernate to work without any entity classes (beans linked to tables),
1. you need to use xml configuration for this. in place of class use entity-name and in place of <property name="something" use <property node="something".
create a hibernate session with entiy-mode as map.
you can use a map to store and retuive information from db. Remember, since you are using map there will be difficulties in 2-way mapping (this was as of 3.3, not sure if its been fixed in later releses)

Hibernate not JPA compliant regarding #Access?

According to my JPA 2.0 book (and online documentation), I should be able to mix field and property access within a single entity or entity hierarchy. The annotation of #Access on the class specifies the default access. When placed on a field or property getter #Access can specify that the default should be overridden for this field.
#Entity
#Access(AccessType.FIELD)
Class Foo {
#Id
int id;
#Column(name = "myfield")
String myField;
#Column(name = "myProp")
#Access(AccessType.PROPERTY)
public int getMyProp () {
return 3;
}
public void setMyProp (int p) {
// do nothing
}
}
This class should result in a table with three columns. However it doesn't with Hibernate...the "myProp" column is missing from the table because apparently Hibernate takes its field vs property cue from the entity ID and runs with it...totally ignoring the JPA spec with regards to #Access.
Can anyone confirm this or did I make a stupid mistake somewhere?
I've seen similar (not the same but similar) issues like HHH-5004 so I wouldn't exclude that this might be a new one (the TCK doesn't seem exhaustive). But what version of Hibernate are you using? Did you try with the latest?
Based on the docs your code seems to be right. The #Access(AccessType.FIELD) annotation on top is unnecessary, because you annotated the field int id;
This tells hibernate to use field access. I tried a very similar example with annotations and xml config mixed. This leads to the same behaviour, so it's probably a bug in hibernate.
I tried with hibernate 3.5.3

Categories

Resources