Very basic question about data modeling - java

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
}

Related

DTOs with different granularity

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

hibernate jpa update two field on persisit and read from one only

one quick question for java hibernate/jpa users.
I have two tables(entities) A and B with relations as A has many B (one to many). Entity A has Set of values B in java.
Due to read performance issue i want to implement master-details denormalization, so i want to store raw Set object (maybe serialized) directly in entity A (because many to one relation cost me to much cpu time because of read by jpa (update is not an issue)).
The problem is, can i achieve something like that getBs always returns me denormalized object (so its fast) and addB adds new B to Set and updates denormalized object with new raw data that is prepared for faster read?
its oracle db.
entity example:
class A {
Long id,
String name;
Set<B> arrayOfBs;
byte[] denormalizedArrayOfB;
getArrayOfBs() {
return (Set<B>) denormalizedArrayOfB;
}
addArrayOfBs(B b) {
//persist b
// update and persist denormalizedArray with new b
}
//getters and setters...
}
class B {
Long id;
A reference;
String x;
String y;
//getters and setters...
}
That's complicated. There are better approaches to your problem:
You can simply replace the one-to-many association with a DAO query. So whenever you fetch the parent entities you won't be able to get the children collection (maybe they are way too many). But when you want to get a parent's children, you simply run a DAO query, which is also easier to filter.
You leave the children collection, but you use an in-memory cache to save the fully initialized object graph. This might sounds like a natural choice, but most likely you're going to trade consistency for performance.

Hibernate: Doman Model to JPA Entity/DTO & Merge() Design pattern or best practice

The recommended way of using merge() is to first get the DTO first before inputting the changes.
public void merge(PersonModel model) {
Person inputDTO = PersonBuilder.build(model)
Person dto = get(pk)
dto.setName(inputDTO.getName())
dto.getChildren().clear()
Iterator<Child> iter = inputDTO .getChildren().Iterator();
while(iter.hasNext()){
dto.getChildren().add(iter.next());
}
dto.merge();
}
Is there a more elegant way of performing such operation translating domain model to dto and merging it so that no data are accidentally deleted.
Example of problem:
Hibernate: prevent delete orphan when using merge();
I find the need to clear the list and adding it very wasteful.
Can someone recommend me a design pattern or a way to code it properly?
Thank you
ADD ON:
1) Possible to use Hibernate Hashset to replace List? Will hibernate hashset replace elements base on primary keys?
any help?
"The recommended way of using merge() is to first get the DTO first before inputting the changes"
Who recommended you to do this?
"Is there a more elegant way of performing such operation translating domain model to dto and merging it so that no data are accidentally deleted."
I don't think you can translate domain objects to DTOs. A DTO is just about data, a domain object is data, behaviour and context. Completely different.
If you don't have behaviour and context in your domain objects (a.k.a. anemic domain model), you don't need an extra DTO layer that just duplicates the objects.
Because you tagged this question with Hibernate and mentioned it in your question, you don't need to call merge yourself because you just got the object from the database and Hibernate will flush the session to synchronize the changes with the database.
"Possible to use Hibernate Hashset to replace List? Will hibernate hashset replace elements base on primary keys?"
I would replace the List with a Hashset, since the table where the data is going to be stored is a set, not a list (you can't have duplicate records). A hashset will not replace elements based on primary keys. A set (any set, Hibernate's implementation is no different) works by preventing duplicates. It uses your equals() and getHashCode() implementation to find out if there is already an object in that set. If that is the case, it won't be added but it keeps the original.

hibernate mapping "rules"

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).

Order multiple one-to-many relations

I have a search screen, using JSF, JBoss Seam, and Hibernate underneath. There are columns for A, B, and C, where the relations are as follows:
A (1< --; >*) B (1< --; >*) C
Let's say A has a List< B > and B has a List< C > (both relations are one-to-many).
The UI table supports ordering by any column (ASC or DESC), so I want the results of the query to be ordered. This is the reason I used Lists in the model.
However, I got an exception that Hibernate cannot eagerly fetch multiple bags (it considers both lists to be bags). There is an interesting blog post here, and they identify the following solutions:
Use #IndexColumn` annotation (there is none in my DB, and what's more, I want the position of results to be determined by the ordering, not by an index column)
Fetch lazily (for performance reasons, I need eager fetching)
Change List to Set
I changed the List to Set, which by the way is more correct, model-wise.
First, if don't use #OrderBy, the PersistentSet returned by Hibernate wraps a HashSet, which has no ordering. So, when I iterate over it in the UI, the order is random, whatever ordering the database did.
Second, If I do use #OrderBy, the PersistentSet wraps a LinkedHashSet, which has ordering, and is what I would like. However, the OrderBy property is hardcoded, and takes precedence over whatever ordering I set both using Collections (link) or HQL (link). As such, all other ordering I request through the UI comes after it.
I tried again with Sets, and used SortedSet (and its implementation, TreeSet), but I have some issues:
I want ordering to take place in the DB, and not in-memory, which is what TreeSet does (either through a Comparator, or through the Comparable interface of the elements).
I found that there is the Hibernate annotation #Sort, which has a SortOrder.UNSORTED and you can also set a Comparator. I still haven't managed to make it compile, but I am still not convinced it is what I need.
One of the requirements is for the sorting to take place in the DB.
Created a simple Maven project and committed it as a Google Code project. This is my personal playground for the problem.
What's the point of ordering in the DB when the same result set can be reordered by any column? If you need to hit the DB every time when a different column is clicked on the UI, you just create a performance issue for yourself. This is exactly the case when it makes sense to order the set in memory.
About bags and lists, this is what the Hibernate bok has to say:
Bags may not be sorted (there is no TreeBag, unfortunately), nor may lists; the
order of list elements is defined by the list index.
Based on what Hibernate in Action said and the workaround provided by your own answer, you could sort your collection at runtime to avoit your exception
#Entity
public class Aa {
private List<Bb> bbList - new ArrayList<Bb>();
#OneToMany
public List<Bb> getBbList() {
return bbList;
}
#Transient
public List<Bb> getBbListSortedBySomeProperty() {
Collections.sort(bbList, new Comparator<Bb>() {
public int compare(Bb o1, Bb o2) {
return o1.getSomeProperty().compareTo(o2.getSomeProperty());
}
});
return bbList;
}
}
Be aware someProperty must implement Comparable
...
#Entity
public class Bb {
private List<Cc> ccList - new ArrayList<Cc>();
#OneToMany
public List<Cc> getCcList() {
return ccList;
}
}

Categories

Resources