Transpose result of hibernate query into list of POJOs - java

I got a generics class that contains runQuery method that has following code setup:
public Object runQuery(String query) {
Query retVal = getSession().createSQLQuery(query);
return retVal.list();
}
I am trying to figure out how to transpose the returned values into a list of Check objects (List):
public class Check {
private int id;
private String name;
private String confirmationId;
//getters and setters
}
Most queries that i run are actually stored procs in mysql. I know of native queries and resultTransforms (which if implemented would mean i have to change my generics and not after that).
Any ideas how i can accomplish this with current setup?

You can find tutorials on ORMs ( What is Object/relational mapping(ORM) in relation to Hibernate and JDBC? ).
Basically, you add annotation to your Check class to tell hibernate which java fields matches which DB field, make a JPQL (it looks like SQL) request and it gets your object and maps them from DB to POJO.
It's a broad subject, this is a good start: https://www.tutorialspoint.com/hibernate/hibernate_quick_guide.htm
It will require some configuration, but that's worth it. Here's one tutorial on annotation based configuration: https://www.tutorialspoint.com/hibernate/hibernate_annotations.htm but with less explanations on how ORM works (there's also EclipseLink as an ORM)
Else, you could make you're own mapper, which takes values from a ResultSet, and set them in your class. For a lot of reason, I would recommand using an ORM than this method (Except maybe if you have only one class that is stored in the DB, which I doubt).

Related

Hibernate: custom entity name

Let's say I have an entity with a very long name:
#Entity
public class SupercalifragilisticexpialidociousPanda
{
...
}
Using Hibernate to persist it to a Postgres DB works flawlessly. Oracle, however, doesn't allow for table/column/index names longer than 30 characters.
That should be easy to fix, since i can just specify the table name manually, like this:
#Entity
#Table(name="SuperPanda")
public class SupercalifragilisticexpialidociousPanda
{
...
}
Now everything is back to working perfectly... except that any references I have to the entity in other tables still use the long class name ("SupercalifragilisticexpialidociousPanda") instead of the short table name ("SuperPanda").
For instance, if the entity has an embedded ElementCollection, like this:
#ElementCollection
private Set<String> nicknames;
Hibernate will try to create a DB like this: create table SupercalifragilisticexpialidociousPanda_nicknames, which will naturally cause an ORA-00972: identifier is too long error.
The same thing also happens for #OneToOne associations, where the lookup column would be called something like supercalifragilisticexpialidociousPanda_uuid, which also fails with oracle.
Now, one option would be to add a #CollectionTable(name="SuperPanda_nicknames") and #Column(name="...") annotation manually to every field that references this entity, but that's a lot of work and really error-prone.
Is there a way to just tell Hibernate once to use the short name everywhere a reference to the entity is required?
I also tried setting the entity name, like this:
#Entity(name="SuperPanda")
#Table(name="SuperPanda")
public class SupercalifragilisticexpialidociousPanda
{
...
}
... but it doesn't fix the issue.
What does one normally do in such a case?
Usually people give names for each database thing (table, column, index) by themselves. Letting Hibernate decide for you can lead to problem in future when you decide to refactor something.
All reference can be configured one way or another to use names you decide to use.
Ask specific question in case you can figure out the way to do it yourself.

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

How to convert ResultSet object to one specific POJO class object?

For example i have a Resultset which contain Details about Employee details and I have a table For Employee in database and i am selecting all details from that
I have java POJO class which resembles Employee Table what is the best method to implement convert result set into Employee class object
what is the best way to implement if i have multiple classes Like Employee and multiple tables too how to write a reusable code.
I am Using following notation now.
public Employee{
private int empId;
public setEmpId(int empId){
this.empId = empId;
}
public int getEmpId(){
return this.empId;
}
}
public class SetResultSetToEmployee{
public Employee getEmployee(){
Employee e = new Employee();
e.setEmpId(resultSet.getInt("EmpId"));
return e;
}
}
Mybatis, or ORM like Hibernate may be your best solution.
But, if you really need to use jdbc's ResultSet, and want to convert ResultSet into java Beans, you can check:
ResultSetDynaClass of BeanUtils from apache.
or, write a bit code yourself like this.
I have java POJO class which resembles Employee Table what is the best
method to implement convert result set into Employee class object
If you are aware of JPA, then that will be best bet.. You won't
have to do a typecast to get your POJO object.. JPA works on ORM
(Object Relational Mapping). It directly Maps your POJO object to
Database table.. And when you can directly fetch your object from
database..
And if you have no other choice than using JDBC, then you have no
other choice than TypeCasting.
what is the best way to implement if i have multiple classes Like
Employee and multiple tables too how to write a reusable code.
In case of JDBC, I don't know what kind of Re-usability you are
looking for, but you can implement a DB class, and have all your
Query Templates there.. For any query you want to execute, you can
use that class.. That be comparatively better to go with rather than
have discrete queries, scattered all over your application..
Again if you can use JPA, there is a concept of Entities.. If you
want to work with multiple fetch, update or insert with database, it will be easier for
you.. You can just get appropriate object and dump it in a instance
of your Entity, or dump your object into your database without worrying about any kind of Queries.
For a start of JPA, you can start with any of these links: -
http://docs.oracle.com/javaee/5/tutorial/doc/bnbpz.html
http://www.vogella.com/articles/JavaPersistenceAPI/article.html
JPA-101-Java-Persistence-Explained
Defining-Your-Object-Model-with-JPA
If you really want to write reusable codes use ORM tools like http://www.hibernate.org/.

Lucene/Hibernate Search - Query associated collections?

I'm writing a Seam-based application, making use of JPA/Hibernate and Hibernate Search (Lucene). I have an object called Item that has a many-to-many relation to an object
Keyword. It looks like this (some annotations omitted):
#Indexed
public class Item {
...
#IndexedEmbedded
private List<Keyword> keywords;
...
}
#Indexed
public class Keyword {
...
#Field
private String value;
...
}
I'd like to be able to run a query for all Item object that contain a particular keyword value. I've setup numerous test objects in my database, and it appears the indexes are being created properly. However, when I create and run a query for "keywords.value" = <MY KEYWORD VALUE> I always get 0 results returned.
Does Hibernate Search/Lucene have the ability to run queries of this type? Is there something else I should be doing? Are there additional annotations that I could be missing?
Hibernate Search is perfectly suited for that kind of queries; but it can be done in a simpler way.
On your problem: text indexed by Hibernate Search (Lucene) is going to be Analysed, and the default analyser applies:
Lower casing of the input
Splitting in separate terms on whitespace
So if you're defining the queries as TermQuery (I'm assuming that's what you did, as it's the simplest form), then you have to match against the lower case form, of a token (with no spacing).
Bearing this in mind, you could dump all your keywords in a single Blob String on the Item entity, without needing to map it as separate keywords, chaining them in a single string separated by whitespaces.

Going from PHP Propel to Java Hibernate

First post here...
I normally develop using PHP and Symfony with Propel and ActionScript 3 (Flex 3), using AMF services. This weekend I'm trying my hand at creating a BlazeDS application using Java and Hibernate, and I'm beginning to like Java a lot!!!
After some research this weekend and using the Hibernate Synchronizer plugin for Eclipse, creating classes mapped (excuse my terminology) to tables seem fairly easy, I'm swiftly getting closer to understanding these aspects.
What I want to know however, is how to develop a more comprehensive architecture for my database, specifically in terms of queries, their results and iterating them. Let me ellaborate:
If I have for example an authors table, I'll be creating an Author class which is mapped to the table, with getters and setters etc. This part looks pretty standard in terms of Hibernate.
Furthermore, I would probably need a Peer class (like in Propel for PHP) to for example do queries which will return a List/Array containing Author instances.
So I would have (speaking under correction) the following classes:
Author
- represents a single row with getters and setters.
AuthorsPeer
- has for example functions like AuthorsPeer::getAuthorsByCountry('USA'); or
- AuthorsPeer::getRetiredAuthors(); or AuthorsPeer::getAuthorsWithSwineFlu();
- ... get the picture. :)
- which return an AuthorsList as it's result...see next point.
AuthorsList
- a collection/list of Author with functions for iterating getNext(), getPrevious() etc.
Is this the way it's meant to be in Hibernate, or am I missing the plot? Am I noticing a Design Pattern here, and not noticing it? Do I need to have something like AuthorsList, or does Hibernate provide a generic solution. All in all, what's the norm with dealing with these aspects.
Also, if I have a Books table, these are related with Authors, if I call say
Author myAuthor = Authors::getAuthor(primaryId, includeBooks);
can Hibernate deal with returning me a result that I can use as follows:
String title = myAuthor.books[0].title;
What I'm asking is, do queries to Authors relating to Books table result in Hibernate returning Authors with their Books all nested inside the Authors "value object" ready for me to pounce with some iteration?
Thanks in advance!
The answer to most of your questions is yes. What you should really look into is how to map one-to-many relationships in Hibernate. In your case, the author is the "one" and the books are the many. Associative mappings are described there. If you are using Annotations with Hibernate (which I highly recommend over XML files), you can find out how to do associations with annotations here.
The great thing about hibernate is that you don't have to do much to manage the relationships. The following is a code snippet of what you would need for your Author-Book relationship.
#Entity public class Author {
#OneToMany(mappedBy="author")
public List<Book> getBooks() {
return books;
}
...
}
#Entity public class Book {
public String getName() {
return bookName;
}
#ManyToOne
public Author getAuthor() {
return author;
}
...
}
To get the Authors from the table, you would use the Criteria API or HQL. I prefer the Criteria API because it goes with Java's general programming feel (unlike HQL). But your preference may differ.
On a side note: You should not create an "AuthorsList" class. Java generics does the job for you:
List<Author> myAuthors = new ArrayList<Author>();
//iterate like so
for(Author author: myAuthors) {
//do something with current author
}
//or just grab 1
Author firstAuthor = myAuthors.get(0);
Java handles compile time checks against the types so you don't have to.
Basically the answer is yes, kinda. :) If you fetch a single Author and then access the collection of Books, Hibernate will lazy load the data for you. This actually isn't the most performant way to do this but it is convenient for the programmer. Ideally you want to use something like HQL (Hibernate Query Language) or its Criteria API to execute a query and "eager fetch" the collection of books, so that all data can be loaded with a single SQL query.
http://docs.jboss.org/hibernate/stable/core/reference/en/html/queryhql.html
Otherwise if you access an Author that has say 500 Books associated to it, Hibernate may issue 500 + 1 SQL queries against the database which is of course incredibly slow. If you want to read more about this, you can Google "n + 1 selects problem" as it's commonly referred to.

Categories

Resources