Is it possible to do a one-to-one mapping to a property, not using primary keys? Basically, what i want to do is to have a property in my "Parent" class, which only holds one reference to one of its children, based on some rule. For example, it could be "last added child". I know this is fairly simple to do with queries, but is it possible to have "intelligent" properties? So you dont have to write anything besides .load(Parent.class, pk) and then work with the instance from there on.
Same question applies for one-to-many relationships, would it be possible to apply rules for that as well? And finally, would it be possible to integrate these rules with paramenters to the getmethod?
So you could have a getChildren(from, to) ish method :)
I would try using the formula attribute. This will allow you to define more complex mappings by using SQL, columns, or other expressions. I'll have to look into this more when I get home but here are some examples\articles to get you started. Apparently the source code also has examples at org.hibernate.test.onetooneformula
Many-to-One Formula Forum Post
O'Reilly Hibernate 3 Formulas Article
Hibernate Example Mappings
Hibernate entities are Java objects. Nothing stops you from writing logic into these objects. Actually it's a good thing if you do. You could have something like this:
#Entity
public class Parent {
...
#OneToMany
private Set<Child> children;
...
public Set<Child> getChildren() {
if (children == null) {
children = new HashSet<Child>();
}
return children;
}
public Child getLastAddedChild() {
for(Child child: getChildren()) {
... logic ...
}
return lastAddedChild;
}
}
Note that this implementation is not optimized, it's just an example. But you can do all sorts of things, like having a #Transient field for holding the last added child (using lazy initialization in the getLastAddedChild() method), or maybe hide your collection and use a method to add children to your object, etc.
As I said, hibernate entities are Objects. In a good OO desing, real objects have behavior associated with it. I would advise you to do some research on DDD (Domain Driven Design).
Related
I have an entity that has a relation to a very large table ( > 100k Rows ). Now I am asking myself if I should express that relation really in my channel entity because would never call getProducts directly to load all products into memory. I would rather go through a product repositiory and query for a very specific subset for that channel.
I have only put it there so it's more readable from a client perspective.
#Entity
#Table(name = "Channel")
public class Channel {
#OneToMany(fetch = FetchType.LAZY)
#JoinColumn(name = "product_id")
private List<Product> products;
public void setProducts(List<Product> products) {
this.products= products;
}
public List<Product> getProducts() {
return this.products;
}
}
Don't put that in a entity definition at all. You see what is often missed is that name #OneToMany is very misleading. As there is no possibility to limit the number of items you are loading. It can practically be used only when Many means Few :). The Hibernate Guru explains it better then me
Of course the join is executed lazily meaning that as long as it is not used it will do no harm. But why tempt faith. Writing query in a repo gives you ability for pagination and you can narrow the results to the one you will truly need.
The other side of the equation is more useful. So if you have on the child entity annotation #ManyToOne leave it there. It is good if you update parent from context of a child.
In short : no.
I think what you are asking may be opinion-based, but here is what I tend to do : remove all "non-navigable" relationships.
If you are using some generator to get JPA entities from a database model, the generator will create only bi-directional relationships. You need to remove all the relationships you will not used through the ORM mechanisms (for readability, maintainability and performance (in case someone would have the idea to remove the "lazy" indication or to call a getter on the collection in a transaction)).
For example, a User will be linked to a Language (many-to-one), but you don't want the (one-to-many) relationship between Language and User, even if at some point you will need to know in a report screen how many user speak which language.
Please don't ask me why I need to do this, as even if I think I could find another way to solve my specific problem, I want to understand HQL and its limits more.
Given the following entities
#Entity
class Child {
private String someAttribute1;
.....
private String someAttributeN;
#ManyToOne(EAGER)
private Parent parent;
}
class Parent {
private String someParent1;
....
private String someParentN;
}
If I select Child then Hibernate automatically fetches all columns from Child and Parent in a single joined SQL, and that is the typical desired case.
Sometimes I know that, for entities mapped with a large number of columns, I need only a subset.
If I select item.someAttribute1 as someAttribute1, item.someAttribute2 as someAttribute2, item.someAttribute3 as someAttribute3 from Child item etc. tied to a ResultTransformer I can let Hibernate return me only 3 columns from the SQL, or more columns if I list them. OK, that is cool and works like a charm.
However if I need to fetch only, say, 3 columns from Child and 2 from Parent, while the rest can be null, and materialize a Child entity with its relationship, I cannot write the following
select item.someAttribute1 as someAttribute1, item.someAttribute2 as someAttribute2, item.someAttribute3 as someAttribute3, item.parent.someParent1 as parent.someParent1, item.parent.someParent2 as parent.someParent2 from Child item left join item.parent
The above does not work because Hibernate does not allow an alias to be composed. It disallows me to use as parent.someName clause because aliases should probably be flat.
Just to tell a counter example, in languages such as LINQ the problem does not apply
from Child c in children
select new Child {
SomeAttribute1 = c.someAttribute1,
SomeAttribute2 = c.someAttribute2,
Parent = new Parent {
Attribute1 = c.Parent.Attribute1,
.......
}
}
With the above statement, Entity Framework will only fetch the desired columns.
I don't want to make comparison or criticism between Hibernate for Java and Entity Framework for C#, absolutely.
I only have the need to fetch a subset of the columns that compose an entity with a #ManyToOne relationship, in order to optimize memory and bandwidth usage. Some columns from the child entity and some from the parent.
I just want to know if and how is it possible in Hibernate to achieve something like that. To populate parent attribute in the result set with an object of class Parent that is populated with only a subset of columns (the rest being null is no problem). I am using ResultTransformers happily
There are two problems with it.
Hibernate doesn't allow to use nested aliases like as parent.someName in HQL. It produces a parsing error. But you can use nested aliases with Criteria using Projections.property("parent.someName").
Hibernate doesn't have a result transformer to populate result objects using nested aliases.
You can use Criteria requests with a custom result transformer as described here
How to transform a flat result set using Hibernate
I'm on a project that uses the latest Spring+Hibernate for persistence and for implementing a REST API.
The different tables in the database contain lots of records which are in turn pretty big as well. So, I've created a lot of DAOs to retrieve different levels of detail and their accompanying DTOs.
For example, if I have some Employee table in the database that contains tons of information about each employee. And if I know that any client using my application would benefit greatly from retrieving different levels of detail of an Employee entity (instead of being bombarded by the entire entity every time), what I've been doing so far is something like this:
class EmployeeL1DetailsDto
{
String id;
String firstName;
String lastName;
}
class EmployeeL2DetailsDto extends EmployeeL1DetailsDto
{
Position position;
Department department;
PhoneNumber workPhoneNumber;
Address workAddress;
}
class EmployeeL3DetailsDto extends EmployeeL2DetailsDto
{
int yearsOfService;
PhoneNumber homePhoneNumber;
Address homeAddress;
BidDecimal salary;
}
And So on...
Here you see that I've divided the Employee information into different levels of detail.
The accompanying DAO would look something like this:
class EmployeeDao
{
...
public List<EmployeeL1DetailsDto> getEmployeeL1Detail()
{
...
// uses a criteria-select query to retrieve only L1 columns
return list;
}
public List<EmployeeL2DetailsDto> getEmployeeL2Detail()
{
...
// uses a criteria-select query to retrieve only L1+L2 columns
return list;
}
public List<EmployeeL3DetailsDto> getEmployeeL3Detail()
{
...
// uses a criteria-select query to retrieve only L1+L2+L3 columns
return list;
}
.
.
.
// And so on
}
I've been using hibernate's aliasToBean() to auto-map the retrieved Entities into the DTOs. Still, I feel the amount of boiler-plate in the process as a whole (all the DTOs, DAO methods, URL parameters for the level of detail wanted, etc.) are a bit worrying and make me think there might be a cleaner approach to this.
So, my question is: Is there a better pattern to follow to retrieve different levels of detail from a persisted entity?
I'm pretty new to Spring and Hibernate, so feel free to point anything that is considered basic knowledge that you think I'm not aware of.
Thanks!
I would go with as little different queries as possible. I would rather make associations lazy in my mappings, and then let them be initialized on demand with appropriate Hibernate fetch strategies.
I think that there is nothing wrong in having multiple different DTO classes per one business model entity, and that they often make the code more readable and maintainable.
However, if the number of DTO classes tends to explode, then I would make a balance between readability (maintainability) and performance.
For example, if a DTO field is not used in a context, I would leave it as null or fill it in anyway if that is really not expensive. Then if it is null, you could instruct your object marshaller to exclude null fields when producing REST service response (JSON, XML, etc) if it really bothers the service consumer. Or, if you are filling it in, then it's always welcome later when you add new features in the application and it starts being used in a context.
You will have to define in one way or another the different granularity versions. You can try to have subobjects that are not loaded/set to null (as recommended in other answers), but it can easily get quite awkward, since you will start to structure your data by security concerns and not by domain model.
So doing it with individual classes is after all not such a bad approach.
You might want to have it more dynamic (maybe because you want to extend even your data model on db side with more data).
If that's the case you might want to move the definition out from code to some configurations (could even be dynamic at runtime). This will of course require a dynamic data model also on Java side, like using a hashmap (see here on how to do that). You gain thereby a dynamic data model, but loose the type safety (at least to a certain extend). In other languages that probably would feel natural but in Java it's less common.
It would now be up to your HQL to define on how you want to populate your object.
The path you want to take depends now a lot on the context, how your object will get used
Another approach is to use only domain objects at Dao level, and define the needed subsets of information as DTO for each usage. Then convert the Employee entity to each DTO's using the Generic DTO converter, as I have used lately in my professional Spring activities. MIT-licenced module is available at Maven repository artifact dtoconverter .
and further info and user guidance at author's Wiki:
http://ratamaa.fi/trac/dtoconverter
Quickest idea you get from the example page there:
Happy hunting...
Blaze-Persistence Entity Views have been created for exactly such a use case. You define the DTO structure as interface or abstract class and have mappings to your entity's attributes. When querying, you just pass in the class and the library will take care of generating an optimized query for the projection.
Here a quick example
#EntityView(Cat.class)
public interface CatView {
#IdMapping("id")
Integer getId();
String getName();
}
CatView is the DTO definition and here comes the querying part
CriteriaBuilder<Cat> cb = criteriaBuilderFactory.create(entityManager, Cat.class);
cb.from(Cat.class, "theCat")
.where("father").isNotNull()
.where("mother").isNotNull();
EntityViewSetting<CatView, CriteriaBuilder<CatView>> setting = EntityViewSetting.create(CatView.class);
List<CatView> list = entityViewManager
.applySetting(setting, cb)
.getResultList();
Note that the essential part is that the EntityViewSetting has the CatView type which is applied onto an existing query. The generated JPQL/HQL is optimized for the CatView i.e. it only selects(and joins!) what it really needs.
SELECT
theCat.id,
theCat.name
FROM
Cat theCat
WHERE theCat.father IS NOT NULL
AND theCat.mother IS NOT NULL
I'm converting my entity to DTO and I want to set NULL as DTO value for all fields, which are lazy-loaded and not initialized (because I do not want to transfer all the data all the time).
I've tried:
if (!(entity.getNationality() instanceof HibernateProxy))
this.setNationalityFromEntity(entity.getNationality());
But it did not seemed to help.
Any suggestions are welcome!
Thank you!
They way we do this in our Entities is we have boolean methods which do the check in a way that will not trigger the lazy loading. For example, if our Entity had an associated entity called 'associatedSomething', then the method to check if that associated Entity has been lazy loaded would be:
public boolean isAssociatedSomethingLoaded() {
if (associatedSomething instanceof HibernateProxy) {
if (((HibernateProxy)associatedSomething).getHibernateLazyInitializer().isUninitialized()) {
return false;
}
}
return (getAssociatedSomething() != null);
}
NOTE: It's important not to use getAssociatedSomething() in the check, as this makes sure that the associated Entity does not get lazy-loaded during the check.
The class is always a proxy, whether it's initialized or not, so you're going to exclude it every time if you just check for instances of proxy. The Lazy Load does not cause the Proxy reference on the entity to be replaced with a reference to a new object, it just populates the fields.
To find out if it's actually initialized you need to ask it!
if (HibernateProxy.class.isInstance(entity.getNationality())) {
HibernateProxy proxy = HibernateProxy.class.cast(entity.getNationality());
if (!proxy.getHibernateLazyInitializer().isUninitialized()) {
this.setNationalityFromEntity(entity.getNationality());
}
}
The mere possibility of being able to invoke a getter for some state that shouldn't be available for a use case is problematic in my opinion, but that's a different story. I would suggest you implement a proper DTO approach instead to avoid accidental errors.
I created Blaze-Persistence Entity Views for exactly that use case. You essentially define DTOs for JPA entities as interfaces and apply them on a query. It supports mapping nested DTOs, collection etc., essentially everything you'd expect and on top of that, it will improve your query performance as it will generate queries fetching just the data that you actually require for the DTOs.
The entity views for your example could look like this
#EntityView(Person.class)
interface PersonDto {
String getNationality();
}
Querying could look like this
List<PersonDto> dtos = entityViewManager.applySetting(
EntityViewSetting.create(PersonDto.class),
criteriaBuilderFactory.create(em, Person.class)
).getResultList();
Suppose I have to develop a simple data model in Java for Order, which contains Order Items. It looks like Order should hold a reference to a collection Order Items Now what if Order and Order Items are stored in a database? Should the Order still hold a reference to the collection or just a simple function retrieveItemsByOrderId should be provided instead?
Now what if Order and Order Items are stored in a database? Should the Order still hold a reference to the collection or just a simple function retrieveItemsByOrderId should be provided instead?
This would depend on how your object model is used by the persistence layer to map classes to the database tables. If you are using Hibernate/JPA/EclipseLink/Toplink or a similar ORM framework, you would merely have a getter method in your Order class that would return the collection of OrderItem instances. Partial code representation would be:
class Order
{
private long id;
private Set<OrderItem> orderItems;
...
public Set<OrderItem> getOrderItems()
{
return orderItems;
}
public void setOrderItems(Set<OrderItem> orderItems)
{
this.orderItems = orderItems;
}
}
class OrderItem
{
private Order order;
...
public Order getOrder()
{
return order;
}
public void setOrder(Order order)
{
this.order = order;
}
}
I haven't listed all annotations in use by the frameworks, including the keys for each entity class, but you'll need to do this to get things working. The salient points however are:
each instance of an Order class contains the Id, which may be the natural key (or may be a generated one).
invoking the getOrderItems method will result in the Set of order items associated with an order to be returned. Note that most ORMs will lazily fetch collections, so you'll need to understand a few more concepts like working with managed and detached entities to actually get this to work; you might need to write an application service to do the work of merging detached entities and then fetch the collection.
One of the comments stated that there is no need to reference the Order from the OrderItem class. This would lead to a unidirectional relationship instead of a bidirectional one. You can use unidirectional relationships in most ORM frameworks, but consider the following:
It would not be trivial to maintain referential integrity (using foreign keys) for unidirectional relationships; this would depend on your ORM framework. Some ORM frameworks might allow you to not have a reference to Order from OrderItem without any further effort on your part, while others might require you to use a Join table. If you are persisting an object graph in the database, then it is imperative to know which OrderItem maps to an Order; by removing the reference from the OrderItem, you will be forced to map this information elsewhere, in a different entity and usually resulting in a different table; this is the Join table that are referred to previously.
Unidirectional relationships are sufficient for most uses. If the Order is responsible for accessing OrderItem instances, then you do not need bidirectional relationships. But if you find yourself needing to access the Order for an OrderItem, then you will need a bidirectional relationship. I would suggest reading the Mutual Registration Pattern, so that you will always be able to maintain referential integrity irrespective of any mutation operations performed on Order or OrderItem classes in such a case. Without that pattern, you are almost always going to find yourself seeing vague, unexplained and incorrect object graphs resulting in an inconsistent database state.
If you are not using ORM or you don't intend to, then it would depend on you are accessing the OrderItem instances; in short, it depends on how you are writing your persistence layer. If you are using the DAO pattern, then adding a new method retrieveItemsByOrderId into your DAO interface would be the solution.
I think you should keep a reference to OrderItem collection in your Order model class. Then, you could implement the method getOrderItems() that retrieves the items from the db based on the order id.
This query should be performed only if you need to access the order items (search for LAZY LOADING) and not every time you load the Order entity from DB.
Using a reference to OrderItem collection in your Order model class will leverage your application in case you need to access twice the order items in the same request-response flow.
A skeleton of getOrderItems() method would be like this:
public List<OrderItem> getOrderItems(){
if(this.orderItems==null)
// perform the query
// set the this.orderItems values
}
return this.orderItems
}