hibernate left join lazycollection untouchable - java

I got something like this:
Criteria crit = session.createCriteria(Parent.class,"p");
parentsList = crit.createCriteria(
"childSet","c",
JoinType.LEFT_OUTER_JOIN,
Restrictions.eq("jt.2ndParentDto.pk2ndParentDto", pk2ndParent))
.list();
My query returns a list of parents with one child each or none, i already tested the logged query directly, so i am pretty sure of it.
I have to retrieve a list of children, so i am adding the parent and creating the ones missing.
List<ChildDto> list=new ArrayList<ChildDto>();
for(ParentDto item:parentsList){
Iterator<ChildDto> it=item.getChildSet().iterator();
if(it.hasNext()){
ChildDto dto = it.next();
dto.setParentDto(item);
list.add(dto);
}
else{
ChildDto dto = new ChildDto();
dto.setParentDto(item);
list.add(dto);
}
}
return list;
By calling item.getChildSet().iterator() hibernate loads the entire collection so i cannot call item.getChildSet().iterator().hasNext to check if there is something in the set, and i cannot call item.getChildSet().size() neither for the exact same reason...
then how?, what else is there?, i am currently out of ideas, how can i get the only item of the set if there is one?
Update: I just tried Extra lazy loading, but it doesn't change for better or worse...
item.getChildSet().iterator() still causes to load the entire collection.
And when i do item.getChildSet().size() hibernate triggers a count... so i always get size of the entire collection (no use).
And that's pretty much it =/
Update: I got it working with a projection by getting a list of Object[] items, and manually creating the classes.
I don't like to do this because, with a change to the Hbm, you're forced to maintain queries of this kind, so i try to avoid this as much as possible.

I'm not sure I understand exactly what you're asking, but I think you're looking for Hibernate "extra lazy" collections, which allow you to get some information about a collection, including the size, without initializing the entire collection, as well as load large collections into memory in batches, rather than all at once.

Can you change the query to return the child records instead? That way you won't get the whole collection. I am not begin clear. Can you just get the child objects from the database, then call something like getParent() to get the parents you need?

Related

Java collection : criteria based traversing or another view to a collection

Is there any way or if any java library available which can let me traverse through selected list items only(not all) which satisfies the condition?
For example: I have a list of employee, and I want to traverse the list of employees who are manager only. I don't want to put a condition or filter but want to traverse the list of manager only.
For this, I can define the criteria while creating the list. So every time, when I'll add an item to the list a pointer to a list item, which satisfies the criteria, will be saved in another list.
It's like providing another view to original list.
Although it can be done using filter, but I would have to basically access each list item, compare and then process.
It can have memory overhead as it'll maintain extra list for each criteria, but I believe it'll reduce processing time.
I am expecting that my list would not contain more than 30 items on average.
Update
After some brainstorming, I have come up with below solution.
View<T>
List<T>
boolean checkCondition(T);
boolean updateView(T);
managerView
boolean checkCondition(T){
return token.getDesignation == designation.MANAGER;
}
salaryView
boolean checkCondition(T){
:
}
ViewableList<T> list
list.addView(managerView)
list.addView(salaryView)
ViewableList<T>
List<View<T>> views;
add(T){
originalList.add(T);
foreach views{
if(view.checkCondition(T)){
view.add(T);
}
}
}
addView(View){
views.add(view)
}
I can achieve Insert, Search, and Delete operation easily. But I am still finding difficulty to update the view when the field of view of an object is updated.
Possible solutions
I annotate list item's field; Write an aspect. So whenever the value of annotated field is changed, it can call updateView() of corresponding view.
Employee{
#View(type=DesignationView.class)
Designation designation;
}
But there is a chance that a field is used in constructing multiple views. So I would have to pass list of view classes in #View annotation, which looks pretty odd. Moreover, I want to avoid use of reflection and aspect due to performance. Otherwise there'll not be any sense to put all this effort.
Please lemme know if you have an idea how I can implement it.
Wouldn't it be better if you use Map. In this map, key could be category and value will be list. So when traversing only get the entry for that key.
And how do you expect such a thing to be coded in such a way as to be so generic that it's useful as a general purpose library rather than specific to your very narrow requirements?
Which would be the only kind of implementation that it is a sensible idea to release as a standalone library of course.
So no, something like that isn't going to exist. You're going to have to create some of your own code.

JPA query getResultList unmodifiable list?

I have started using JPA 2 / JPQL. I see a lot of examples where query.getResultList() is returned. But have never seen the resultlist marked as unmodifiable. For instance:
final TypedQuery<String> query = entityManager.createNamedQuery("Some query", String.class); //$NON-NLS-1$
return query.getResultList();
Is there any reason this should not be marked as unmodifiable, if I dont expect to change the result set returned from the database?
Any reason this could cause issues?
It's more there's no reason to mark it as unmodifiable. If you want to change the contents of the list, feel free, it's just the results from a database.
The list in the query object has no reason to make it unmodifiable. It's just an in memory store of what's in the database at that point so modifying this list doesn't make changes to the database unless you actually persist this new list.

Fast way to count the number of relationships for a node

I am trying to count the number of outgoing relationships of a particular type a node has. My code currently looks like this:
int count = 0;
for (Relationship r : node.getRelationships(RelationshipTypes.MODIFIES, Direction.OUTGOING))
{
count++;
}
return count;
The return type of getRelationships is Iterable so I can't use size() or equivalent. I am trying to avoid having to pull every relationship out of the database because some nodes have lots of relationships ( > 5 million). Is there a faster way of doing this?
No. The way neo4j stores relationships on disk for a node is in a linked list, and they do not keep any type of statistics for nodes or relationships. In order to get a count, you will have to go through all relationships for the node, of that type.
Even if you have a cache, with which they store it more efficiently, the system may still not provide a full picture. You method is the best method.
I would try to store outgoing in a data structure and get the size of the structure. This may take more time when the objects are initialized but it seems like the easiest way to quickly get size.
if node.getRelationships(RelationshipTypes.MODIFIES, Direction.OUTGOING) is returning a type of Collection then
to know the number of outgoing relationships of a particular type a node has , you can simply use the following :
int count = node.getRelationships(RelationshipTypes.MODIFIES, Direction.OUTGOING).size();
I see you are using the neo4j api. The other way would be to go with ThinkerPop gremlin query language which is available both for groovy and scala but they will do the same thing internally. As i know neo4j is giving you access trough an iterator because of performance reasons. For instance you could have million relationships but you want to paginate trough the results on the fly. It would be really be slow if Neo4J would return always a collection of relationships. That's why he returns a iterator and gives you access on the fly to the relationships. They are not retrieved from the DB until you need them.
So i would say NO. I hope i could help you.

In Hibernate, why Set is the recommended way to represent many-valued associations

Taken from here: http://docs.jboss.org/hibernate/stable/core/reference/en/html/persistent-classes.html#persistent-classes-equalshashcode
I tend to use List since Criteria returns List, so it makes my code cleaner since I don't have to do conversion.
I do something like so..
#OneToMany(cascade= {CascadeType.PERSIST, CascadeType.REMOVE}, mappedBy="parent")
#Column(name="PARENT_ID")
public List<Menu> getChildMenus() {
return childMenus;
}
If I had use Set there, somewhere in my DAO I will have to convert results returned by Criteria to Set first.
I wonder what the repercussion could be by using List they way I am doing.
Set is used as the child table has a primary key such that a child can only be once in a parent. If you use a list there can be duplicate children in the list and this cannot be saved to the database.

How to reuse a Criteria object with hibernate?

I'm trying to do query result pagination with hibernate and displaytag, and Hibernate DetachedCriteria objects are doing their best to stand in the way. Let me explain...
The easiest way to do pagination with displaytag seems to be implementing the PaginatedList interface that has, among others, the following methods:
/* Gets the total number of results. */
int getFullListSize();
/* Gets the current page of results. */
List getList();
/* Gets the page size. */
int getObjectsPerPage();
/* Gets the current page number. */
int getPageNumber();
/* Get the sorting column and direction */
String getSortCriterion();
SortOrderEnum getSortDirection();
I'm thinking of throwing my PaginatedList implementation a Criteria object and let it work along theese lines...
getFullListSize() {
criteria.setProjection(Projections.rowCount());
return ((Long) criteria.uniqueResult()).intValue();
}
getList() {
if (getSortDirection() == SortOrderEnum.ASCENDING) {
criteria.addOrder(Order.asc(getSortCriterion());
} else if (getSortDirection() == SortOrderEnum.DECENDING) {
criteria.addOrder(Order.desc(getSortCriterion());
}
return criteria.list((getPageNumber() - 1) * getObjectsPerPage(),
getObjectsPerPage());
}
But this doesn't work, because the addOrder() or the setProjection() calls modify the criteria object rendering it in-usable for the successive calls. I'm not entirely sure of the order of the calls, but the db throws an error on getFullListSize() trying to do a "select count(*) ... order by ..." which is obviously wrong.
I think I could fix this by creating an object of my own to keep track of query conditions and rebuilding the Criteria object for each call, but that feels like reinventing yet another wheel. Is there a smarter way, possibly copying the Criteria initially passed in and working on that copy?
Update:
It looks like getList is called first, and getFullListSize is called multiple times after, so, as soon as there's an ordering passed in, getFullListSize will fail. It would make sense to hit the db only once (in getList I'd say) and cache the results, with no need to copy/reset the Criteria object, but still...
Update (again):
Forget about that, once I've done the count I can't do the select, and vice versa. I really need two distinct Criteria objects.
Criteria.setProjection(null);
Criteria.setResultTransformer(Criteria.ROOT_ENTITY);
Will effectively "reset" the criteria between the rowCount projection and execution of the criteria itself.
I would make sure your Order hasn't been added before doing the rowCount, it'll slow things down. My implementation of PaginatedList ALWAYS runs a count query before looking for results, so ordering isn't an issue.
well, DetachedCriteria are Serializable, so you have built-in (if inelegant) deep clone support. You could serialize the initial criteria to a byte[] once on construction, then deserialize it each time you want to use it.
http://weblogs.asp.net/stefansedich/archive/2008/10/03/paging-with-nhibernate-using-a-custom-extension-method-to-make-it-easier.aspx
In that post I spotted a CriteriaTransformer.clone method.
That should copy the criteria object.
You can also set the projection on your getlist method.
Woops I didn't notice you were referring to java hibernate. Anyway, this http://forum.hibernate.org/viewtopic.php?t=939039
forum post should be able to answer your question.
Ugly as it may be I ended up using the serialization trick. I just serialize the DetachedCriteria object to a byte array on construction of the PaginatedList object and de-serialize it when needed. Ouch.
Another thing worth trying:
implement a generic DAO like the one suggested on hibernate's site and pass it to the PaginatedList object, along with a Restrictions object. The PaginatedList object would then do something like
Criteria.forClass(myDAO.getPersistentClass())
.add(myRestrictions)
.addOrder(<someOrder>)
and
Criteria.forClass(myDAO.getPersistentClass())
.add(myRestrictions)
.setProjection(Projections.rowCount());
Haven't tried that yet, but it should work.
There is a better and easy way to clone criteria, just simply:
ICriteria criteria = ...(your original criteria init here)...;
var criteriaClone = (ICriteria)criteria.Clone();
And getting back to Your problem. For pagination I've made a method, which gives me as a result:
1. Total rows count
2. Rows filtered by page & pageSize
In a single query to DB.
ICriteria criteria = ...(your original criteria init here)...;
var countCrit = (ICriteria)criteria.Clone();
countCrit.ClearOrders(); // avoid missing group by exceptions
var rowCount = countCrit
.SetProjection(Projections.RowCount()).FutureValue<Int32>();
var results = criteria
.SetFirstResult(pageIndex * pageSize)
.SetMaxResults(pageSize)
.Future<T>();
var resultsArray = results.GetEnumerable();
var totalCount = rowCount.Value;
public static DetachedCriteria Clone(this DetachedCriteria criteria)
{
var dummy = criteria.ToByteArray();
return dummy.FromByteArray<DetachedCriteria>();
}

Categories

Resources