How does Hibernate work with normalized databases? - java

Preliminary Info
I'm currently trying to integrate Hibernate with my team at work. We primarily do Java web development, creating webapps that provide data to clients. Our old approach involves calling stored procedures with JDBC (on top of Oracle boxes) and storing their results in beans. However, I've heard a lot about the benefits of integrating Hibernate into a development environment like ours so I'm attempting to move away from our old habits. Note: I'm using the Hibernate JPA annotation approach due to simplicity for team adoption's sake.
Specific Problem
The specific issue I'm having currently is using Hibernate with normalized tables. We have a lot of schemas structured like so:
StateCodes (integer state_code, varchar state_name)
Businesses (integer business_id, varchar business_name, integer state_code)
I want to be able to have a single #Entity that has all of the "Businesses" fields, except instead of "state_code" it has "state_name". To my understanding, Hibernate treats #Entity classes as tables. The #OneToMany, #OneToOne, #ManyToOne annotations create relationships between entities, but this is a very simplistic, dictionary-like lookup and I feel like it doesn't apply here (or might be overkill).
One approach I've seen is
#Formula("(select state_name from StateCodes where Businesses.state_code = state_code)")
private String stateCode;
But, given Hibernate's perk of "avoiding writing raw SQL", this seems like bad practice. Not to mention, I'm extremely confused about how Hibernate will then treat this field. Does it get saved on a save operation? It's just defined as a query, not a column, after all.
So what is the best way to accomplish this?

I do not see any reason not use the standard JPA mappings in this case. Short of creating a database view and mapping an entity to that (or using the non-JPA compliant #Formula) then you will have to map as below.
Unless you are providing a means for the State to be changed then you do not need to expose the State entity to the outside world: JPA providers do not need getters/setters to be present.. Neither do you need to Map a State to Businesses:
#Entity
#Table(name = "Businesses")
public class Business{
//define id and other fields
#ManyToOne
#JoinColumn(name = "state_code")
private State state;
public String getStateName(){
return state.getName();
}
}
#Entity
#Table(name="StateCodes")
public class State{
//define id and other fields.
#Column(name = "state_name")
private String stateName;
public String getStateName(){
return stateName;
}
}

Related

Why can't we make a relationship attribute in spring data JPA final as well?

An Owner entity has a #ManyToOne - #OneToMany relationship with the teacher entity. When I annotate each like this
#Entity
public class Product {
...
#ManyToOne(cascade = MERGE)
private final Owner owner;
On the other side, in the Owner Class,
#Entity
public class Owner {
...
#OneToMany(mappedBy = "owner", cascade = MERGE)
private final List<Product> products;
What happens now is that "owner" in the line mappedBy = "owner" turns red. Hovering over it, I get the error that the owner attribute cannot be found.
The error: Cannot find inverse attribute
The solution was simply to remove the final keyword in the attribute owner in the Product class.
It becomes private Owner owner and the error disappears. I don't understand why adding the keyword final causes this problem.
Why does this happen?
Is there a workaround? Can I still make the owner attribute final?
The main idea from the getgo was to make the product class immutable. While this is a challenge, I've managed to find a workaround for most things, but I didn't know how to fix this problem.
JPA does not support immutability. A JPA entity does require a default constructor and getters and setters for properties.
And the fields must not be final.
Technically it would be possible to implement an ORM that ignores final attributes but why should it?
The keyword final says: This gets assigned a value at construction time and never changes after that. This is just not true for JPA entities which get constructed via no-args-constructor and then populated in second step.
If you are looking for an ORM that has better support for immutable classes (constructor with arguments, "wither" methods) you might want to check out Spring Data JDBC.
Full disclosure: I'm Spring Data developer working on both Spring Data JPA and Spring Data JDBC.
I think you have understood immutability concept wrong. Immutability is a concept being forced by the Java language. For example String class is immutable because of the security, caching etc. But in your case Product is an entity class and if you save it in a persistent layer, it is already unique on it's own. So even if you make the Product class immutable, how are you going to keep that consistency during two application loads?. If you are trying to make a Product having owned by only one owner, then do a db check rather than trying to make it immutable in memory.

How to build a relational Java object model over a not-that-relational data model?

I am currently working on several solutions to redesign a web application based on a database that is shared between this application and other running services.
The actual application uses NodeJS, and basically processes data after having exctracted too much information from a table in the database. I think this is wrong, because we should only ask the database for the data we need, and limit processing on the server as these processes imply long loading time for end users.
So I thought I would build a Java API instead, that would use objects that can be easily used by the front part of the application, and use Hibernate or an equivalent component to extract necessary information from database.
But the problem is that the database over which I would build this API, while supposed to be relational (it's postgreSQL), is actually composed of tables that do not communicate between each other : there are no joins between tables, hence no cascade on modifiying related objects. Furthermore, the tables do not correspond directly to objects used in the application. They are more like "super objects" that would contain other sub-objects in a Java model.
Problem is, I cannot recreate a "cleaner" database as it is used by other services (which is probably why it is so weirdly organised, by the way). I should use it as it is, and map the redesigned application to it. I could be allowed to redesign some tables to make them "more relational", but this should have no implications for the other services. That would imply to drastically rewrite some SQL functions, and I am not sure that it is a very efficient solution. That being say, I am not very experienced on writing SQL functions, so maybe that could be a solution in the end.
So, to put it all in a nutshell, what could I do to build an object oriented model using Java, or any other technology that you could think of, to redesign properly the application, without throwing the database or modifying it drastically ?
Any suggestion or lead of research would be greatly appreciated. Also, please tell me if I am not being precise enough, and I will try to improve my question.
Use JPA to map your database records into entities.
This wiki page gives quite a few samples of advanced uses :
multiple tables for an entity :
#Entity
#Table(name="EMPLOYEE")
#SecondaryTable(name="EMP_DATA",
pkJoinColumns = #PrimaryKeyJoinColumn(name="EMP_ID", referencedColumnName="ID")
)
public class Employee {
...
#Column(name="YEAR_OF_SERV", table="EMP_DATA")
private int yearsOfService;
#OneToOne
#JoinColumn(name="MGR_ID", table="EMP_DATA", referencedColumnName="ID")
private Employee manager;
...
}
multiple kind of entities in single table (this sample is mine, there was no code on the wiki ; let's hope I didn't mess it up !) :
#Inheritance
#DiscriminatorColumn(name="DISCRIMINATING_COLUMN")
#Table(name="SOME_TABLE")
public class Generic { ... }
// only maps records from SOME_TABLE where DISCRIMINATING_COLUMN=SOME_VALUE
#Entity
#DiscriminatorValue("SOME_VALUE")
public class firstSpecificType { ... }
// only maps records from SOME_TABLE where DISCRIMINATING_COLUMN=OTHER_VALUE
#Entity
#DiscriminatorValue("OTHER_VALUE")
public class secondSpecificType { ... }
entities from proc calls :
// This stored procedure returns a result set and has one input parameter.
#NamedStoredProcedureQuery(
name = "ReadAddressById",
resultClasses = Address.class,
procedureName = "READ_ADDRESS",
parameters = {
#StoredProcedureParameter(mode=javax.persistence.ParameterMode.IN, name="P_ADDRESS_ID", type=Long.class)
}
)
#Entity
public class Address {
...
}
and many others.

Is mapping of an #Embeddable through a wrapper #Entity possible?

I am currently building a persistence layer for a number of data classes that I can NOT change. These classes have no Id property/field which makes them ill suited for being used in ORM.
A best case scenario for me would have been some sort of auto-generated Ids that would only be present inside the database to set the objects in relation to each other. Sadly this does not seem to be possible using the JPA apis.
Since the above approach did not work out, I decided on trying to use simple wrapper #Entity objects like so:
#Entity
public class ThirdPartyObjectWrapper {
#Id private long id;
#Embedded private ThirdPartyObject myThirdPartyObject;
}
This approach works out nicely in the database, but I am having problems getting the object out of the wrapper and into its place inside another third party object.
public class AnotherThirdPartyObject {
private ThirdPartyObject object; //Actually in a Many-To-One-Relationship
}
Because they are third party objects I'm mapping them through the orm.xml file defining the relationships there. At this point in time the relationship mapping looks like so:
<many-to-one name="object"
target-entity="ThirdPartyObjectWrapper"/>
But with this setup Hibernate tries to insert the ThirdPartyObjectWrapper.id into the AnotherThirdPartyObject.object field, which obviously fails.
My question now is:
Is what I am trying even possible?

Make JPA entity field immutable in REST environment

There are two simple JPA entities for Jersey REST web-service. Basically business item has a creator which refers to a user. When serializing it is not necessarily to show the creator of the business item to the client, so JsonIgnore annotation is there. Assume that I allow every user to update BusinessItem name via HTTP PUT request, but not to update creator value.
#Entity
public class BusinessItem {
#GeneratedValue(strategy = AUTO)
#Id
Long id;
String name;
#JsonIgnore
#ManyToOne
#JoinColumn(name = "creator_id", nullable = false, updatable = false)
User creator;
}
#Entity
public class User {
#GeneratedValue(strategy = AUTO)
#Id
Long id;
String name;
#OneToMany(fetch = LAZY, mappedBy = "creator")
List<PhotoSpot> createdPhotoSpots;
}
The problem is that once PUT request with JSON body is received from a client and deserialized then creator field would be null. Then in order to update entity in a database I would need to retrieve a creator value from the DB by the business item id, substitute in the deserialized entity and only then apply update to the database. This all sounds like not elegant and boiler plate.
What would be an elegant solution for this type of problem?
The direct association between a service and an entity can be a pragmatic design in very simple applications. However in many case this is not a suitable option. Managing properly entity relationships can be a good reason to have a more structured design.
In the usual design of standard MVC applications, it is a good practice not to use the entity directly as a JavaBean accessed via the View / page (the entity is an Enterprise JavaBean in an EJB container, not to be confused) . The implementation of a TransferObject pattern is an usual solution (beware, the sequence documented in that link is for a data retrieval operation, not an update). The controller commonly assumes the construction of the TransferObject. It then becomes a recommended candidate for a DAO operation.
A REST service is not very different from an MVC pattern: in fact this is an Entity-Control-Boundary pattern (in the case of Jersey <= 2 applications, the distinction can be quite subtle, even if this should evolve in Java EE 8). The service itself is a Boundary replacing the View.
In other words, according to Core J2EE Patterns, the elegant solution would be to feed a TransferObject with your PUT parameters: this object is then transmitted to the DAO. Then the DAO layer just has to retrieve a properly managed entity from the database to get the entities relationships and report the transferred values to update into the managed entity while preserving the relationships (this can be done with a DAO).
Java EE design can be quite challenging. The platform provides out of the box components very similar to pattern shapes. But in several cases these are not replacements. For example an EntityManager looks like a DAO. But using an explicit DAO usually provides a clear and understandable code while using directly the EntityManager can be quite verbose as transactions are not encapsulated.
Conclusion
In your situation, what seems important to me is the use of a DAO to encapsulate your database operations (this is only if you really need to map the relationships, otherwise a #Transient annotation would be a solution). You will anyway have to retrieve a managed entity before performing the merge(...) operation. The use of the TransferObject is not mandatory, this is just an advice to have a proper design. In many case this can lead to verbose code. You have several solutions to limit this: a simple Map can limit the code, a utility such as BeanUtils can also be precious.
But avoiding a basic transfer operation in setting up a DAO can be challenging. In your case this would induce the use of a MultivaluedMap in the DAO layer, which does not seem a very good idea on a dependency point of view as it links the Model/Entity and the View/Boundary components. This is probably why Core J2EE patterns introduces the TransferObject.

Object-mapping in Spring JDBC?

I have previously used Hibernate and now I am trying to understand JDBC. I have done loads of research on Spring JDBC but still I could not understand how to create relationships between objects.
Assume I have a Product:
public class Product {
private Long id;
private String nam;
private Customer customer;
//constructor, getters and setters.
}
and a Customer:
public class Customer {
private Long id;
private String name;
private List<Product> products = new ArrayList<Product>();
//constructor, getters and setters
}
The relationship between Customer and Product is #OneToMany.
How to correctly save the product and customer objects in the db using SpringJDBC?
Thank you
It make a lot of sense in quite a few cases to not use a full blown ORM but rely on lower level of abstraction, like Spring JDBCTemplate and RowMapper. iBatis comes to mind as well. And that make sense even in large enterprise solutions.
If you leave the full blown ORM world, you will have to do additional work yourself. For example, you can write an SQL query with a join, returning all customer fields and all products of that customer, and iterate through it to map all that to Java object. In quite a few cases, the code can be as clean as what you would have with an ORM.
Writing all that data is more messy, especially if you need to optimize for stuff that has not been dirtied.
Best use case I can think of is batch processing, where control over data access becomes more important and higher level of abstraction do not necessarily make you more productive.
If you are willing to consider something other than spring or hibernate, sormula can do what you describe. See the one to many example. If you name the foreign key on the many side the same as the primary key on the one side, then you don't need any annotations.
To store a reference to one-side object (Customer) in the many-side objects (Products), you can use the OneToManyCascade#foreignKeyReferenceField. For examples, search the tests in the project for "foreignKeyReferenceField".
If I understand your question correctly, if think if you are not using ORM you would have to do this manually.
In your DAO class for Customer it would first have to persist all the products.
An alternative might be to create a Stored Procedure on the database and have that sort out the correct persistence.
This can be handled very nicely by Spring JDBC, the downside is you know have to manage Java and Stored Procedures.
In your case it might still be two Stored Procedures.
There is also the possibility that QueryDSL and Jooq, thought I haven't had a chance to have a good look at them.
I personally like the Stored Procedure solution, for me the additional over head is worth it, I know others disagree, but I just don't like/buy the ORM deal.

Categories