First off, I'm new to Hibernate.
I have a standalone Java application built in Netbeans, trying to keep to the MVC model as much as possible. My model classes resemble the database tables and columns as much as possible. The database is normalized to avoid redundancy.
However, I noticed that it was convenient to have a certain property available in many of my model classes. This property is available in the database, but in most situations it is necessary to do multiple joins to get it.
Therefore, I added this property to my model classes for easier access.
Example:
Object A has a relation with Object B, which has a relation with Object C. Object C has the property X.
The relations are one-to-many; Object A has the primary key of Object B as a column, and so forth.
Now I want to find all Object A connected to property X. I have to do multiple joins to get the answer. Property X also applies to Object A, but I don't want it as a property for Object A in the database, as that is redundancy. In the application, I add this property X to the class of Object Afor convenient access.
Now I want to implement Hibernate instead of my own designed (service) classes, and I'm not sure what to do with this property. I have defined it as 'Transient' in the POJO, but how do I fill this property? If I let Hibernate perform a get tot the database and return the object (Object A) to me, it will not have this property. Do I need to have an extra constructor with this property and transform Hibernate's object to the one containing this property and return that to the original method that asked for it?
What is the correct way to do this?
If you are using Hibernate you probably have something like this in your class A:
#OneToMany
private Collection<B> listOfB;
In B you will have:
#OneToMany
private Collection<C> listOfC;
So when you get the A Entity from your Database you can get x doing:
a.getlistOfB(0).getListOfC(0).getX();
Related
I'm using Spring MongoDb Data, and I have two classes A and B inheriting from class C.
Both A and B has the '_class' field.
I want to fetch a list of documents with both A and B in them, and have them be mapped to their inheriting objects, but using MongoOperation it seems that it's only possible to put one class entity with each query. Is there a way to fetch a list of both A and B and have them polymorphed to their corresponding java objects? Or fetching the abstract C is the only way to fetch both A and B at the same time?
The single type parameter you hand into the ….find…(…) methods of MongoTemplate is effectively a shortcut to define both the collection to be read and the types of objects to be produced eventually by the document mapping subsystem. It does not restrict the document selection in any way. This effectively implements a type-hierarchy-by-collection approach.
If you want to restrict the query result to only some subtypes, you need to use the Query type's ….restrict(Class, Class…) method that allows to define which nominal types are supposed to be read. That effectively translates in to a constraint against the type aliases being persisted on write, as MongoDB documents don't know anything about types on the client in the first place.
Due to the deprecation of JPublisher since Oracle 12c we're currently considering other ways how we can call stored procedures with complex object types as parameters instead of generated classes and JDBC.
It seems that EclipseLink JPA Extensions is the only tool that can help with it. Following the examples I found I'd be able to call procedures with simple types as arguments. But I wasn't able to annotate my entity classes so that they would map correctly to the PL/SQL Object types in the database when the objects are a bit more complex.
For example we have a stored procedure that has one input and one output parameter of the same Object type A. The type structure is following:
Object type A contains <- Table type B which is table of <- Object type C which contains <- Table type D which is table of <- Object type E.
I figured I shall use the #OracleObject for the Object types and #PLSQLTable for the Table types but I haven't found a way how to correctly combine them together.
I've tried the following:
// All annotations with the required elements
#Embeddable
#Struct
#OracleObject
public class A {
#Column(name = "B")
private B b;
// Getter and setter
}
#Embeddable
#Struct
#PLSQLTable (.., nestedType = "C")
public class B { }
#Embeddable
#Struct
#OracleObject
public class C {}
I've tried to add the #PLSQLTable with the proper annotation elements to class A and/or to class C but the Java and DB objects do not map to each other correctly and I'm getting the java.sql.SQLException: Invalid column typeduring the call.
I'd greatly appreciate if someone could explain to me how to use the annotations to tell the EclipseLink that Object A contains Table B of Object C.
Thank you very much.
Same issue here. I have been going down the path of Spring Data Oracle Extension project. However the example given is a simple pojo, not a complex object.
Despite a lack of examples anywhere I can find, I was able to pull a very complex object back via SqlReturnSqlData(), but can't seem to find a way to insert a complex object into an oracle stored procedure. I have yet to find any full example of how anyone is inserting custom complex Oracle Types. Via Spring or any other way.
I am currently working on a product that works with Hibernate (HQL) and another one that works with JPQL. As much as I like the concept of the mapping from a relational structure (database) to an object (Java class), I am not convinced of the performance.
EXAMPLE:
Java:
public class Person{
private String name;
private int age;
private char sex;
private List<Person> children;
//...
}
I want to get attribute age of a certain Person. A person with 10 children (he has been very busy). With Hibernate or JPQL you would retrieve the person as an object.
HQL:
SELECT p
FROM my.package.Person as p
WHERE p.name = 'Hazaart'
Not only will I be retrieving the other attributes of the person that I don't need, it will also retrieve all the children of that person and their attributes. And they might have children as well and so on... This would mean more tables would be accessed on database level than needed.
Conclusion:
I understand the advantages of Object Relational Mapping. However it would seem that in a lot of cases you will not need every attribute of a certain object. Especially in a complex system. It would seem like the advantages do not nearly justify the performance loss. I've always learned performance should be the main concern.
Can anyone please share their opinion? Maybe I am looking at it the wrong way, maybe I am using it the wrong way...
I'm not familiar with JPQL, but if you set up Hiernate correctly, it will not automatically fetch the children. Instead it will return a proxy list, which will fetch the missing data transparently if it is accessed.
This will also work with simple references to other persistent objects. Hibernate will create a proxy object, containing only the ID, and load the actual data only if it is accessed. ("lazy loading")
This of couse has some limitations (like persistent class hierarchies), but overall works pretty good.
BTW, you should use List<Person> to reference the children. I'm not sure that Hibernate can use a proxy List if you specify a specific implementation.
Update:
In the example above, Hibernate will load the attributes name, age and sex, and will create a List<Person> proxy object that initially contains no data.
Once the application accesses calls any method of the List that requires knowledge of the data, like childen.size() or iterates over the list, the proxy will call Hibernate to read the children objects and populate the List. The cildren objects, being instances of Person, will also contain a proxy List<Person> of their children.
There are some optimizations hibernate might perform in the background, like loading the children for other Person objects at the same time that might be in this session, since it is querying the database anyways. But whether this is done, and to what extend, is configurable per attribute.
You can also tell hibernate to never use lazy-loading for certain references or classes, if you are sure you'll need them later, or if you continue to use the persistent oject once the session is closed.
Be aware that lazy loading will of course fail if the session is no longer active. If for example you load a Person oject, don't access the children List, and close the session, a call to children.size() for example will fail.
IIRC the hibernate session class has method to populate all not-yet-loaded references in a persistent oject, if needed.
Best read the hibernate documentation on how to configure all this.
I've got alot of beans with attributes, which are derived from database tables with JPA. The users shall be able to enter any column name and a value as a string, and the app shall automatically find the correct member in the one of the beans.
I must use JPA, otherwise I would use some JDBC meta data to put all columns and values into a normal map. Is something like this possible with JPA? It only has to work from database to beans, I don't want to persist changes.
If this doesn't work, can I somehow analyze member names programmatically at runtime?
The EntityManagerFactory has a getMetamodel() method, which returns its MetaModel. From this MetaModel, you may ask for the MetaModel of every entity class, and discover all its attributes, their types, etc.
In case the JPA part doesn't work, you can access class members (fields, methods) of your class as follows:
Field[] fs = YouClass.class.getDeclaredFields();
Details for accessing different members are on this link
For a project I am working on, I need to persist a number of POJOs to a database. The POJOs class definitions are sometimes highly nested, but they should flatten okay, as the nesting is tree-like and contains no cycles (and the base elements are eventually primitives/Strings). It is preferred that the solution used create one table per data type and that the tables will have one field per primitive member in the POJO. Subclassing and similar problems are not issues for this particular project.
Does anybody know of any existing solutions that can:
Automatically generate a CREATE TABLE definition from the class definition
Automatically generate a query to persist an object to the database, given an instance of the object
Automatically generate a query to retrieve an object from the database and return it as a POJO, given a key.
Solutions that can do this with minimum modifications/annotions to the class files and minimum external configuration are preferred.
Example:
Java classes
//Class to be persisted
class TypeA {
String guid;
long timestamp;
TypeB data1;
TypeC data2;
}
class TypeB {
int id;
int someData;
}
class TypeC {
int id;
int otherData;
}
Could map to
CREATE TABLE TypeA (
guid CHAR(255),
timestamp BIGINT,
data1_id INT,
data1_someData INT,
data2_id INt,
data2_otherData INT
);
Or something similar.
I would use the standardized Java Persistence API (JPA), preferably with annotations. Regarding your requirements:
This is not required by the specification but most JPA providers (all major implementations do) support DDL generation from the mapping metadata.
EntityManager#persist(Object entity) does that.
<T> T EntityManager#find(Class<T> entityClass, Object primaryKey) does that.
As hinted, JPA is an API, you need an implementation to use it. My preference goes to Hibernate Entity Manager or EclipseLink (see this previous question).
Hibernate can help you solve all the three problems you listed.
(1) You need to annotate your entity classes so Hibernate is able to map between classes/objects to tables/rows. Hibernate uses a convention over configuration approach so it is possible to use just a few annotations and have a complete o/r mapping ready for use. You could use the hibernate.hbm2ddl.auto configuration option to instruct Hibernate to automatically validate/export and schema DDL when the session factory is first created.
(2) / (3) Hibernate has enough information about classes, database schema and mappings to allow it generate SQL statements for simple CRUD operations with minimal effort. You can fine tune how Hibernate loads and persists a tree of objects. Association mapping annotations have the fetch and cascade options that let you specify how associated objects are fetched (lazy / eager) and how operations are propagated through the object tree. Please refer to the Hibernate documentations for the details about these options.
If you are new to Hibernate, I recommend the good Hibernate documentation as reference and the book Java Persistence with Hibernate for the deeper understanding about the framework (it has very good sections about fetching and cascading).
In a typical scenario, Hibernate requires just a bit of configuration (one hibernate.cfg.xml file). You can define the mappings using XML files (no good) or annotations (the "default" option for new projects).
You tagged your question as Hibernate. Have you tried using Hibernate for this?
As long as you define well how collections should be mapped (e.g., one-to-many), I've found it generally very effective for this kind of thing.
The Hibernate tutorials provide a lot of examples for situations that are similar to the code you provided.
A highly recommended framework is JPersist, an extremely simple Database-to-POJO framework. No XML or annotations needed. I use it it my project because if I want a new table object, I simply create a bean.
The issue though in your situation is your wanting something to setup the database for you. Doing that would be very hard and your asking alot from a framework. With JPersist, you should be able to create a db table from class name and columns from fields, and then use phpMyAdmin's designer to resolve references.
5 min of reading the documentation for JPersist now will save hours in development time later.
JPA provides sufficient options to do this. For example you can use #Embeddable and #Embedded:
#Embeddable
class TypeB {
int id;
int someData;
}
class TypeA {
....
#Embedded
TypeB data1;
}
You can either manually create the underlying schema, or let something like hbm2ddl.auto=update to create it for you.