Preventing infinite loop data retrieval with Hibernate - java

I was wondering: Imagine a scenario where e.g.
//POJO
public class User {
private String userName;
private String name;
private String surname;
private List<Blog> blogList;
//All getters and setters are found here and assume they're generated.
}
public class Blog {
private String title;
private String content;
private User author;
private Date datePublished;
private Date dateLastModified;
//All getters and setters have been generated (by Eclipse or NetBeans)
}
Imagine that these objects have been correctly mapped into their respective Hibernate configuration files.
My question:
How would I retrieve my user with the list of all the user blogs on code level? (i.e., not allow hibernate to populate blogList automatically for me.
I want to add paging (i.e. from list 5, retrieve 20 list) and also, if you think carefully, this might be an infinite loop as a Blog has a User entity which has a List<Blog> entity.
How do I prevent this?
PS Just out of curiousity, how would I let Hibernate populate my blogList on the configuration side?
Thanks in advance.

Hibernate detects such loops and doesn't let them happen
You can mark your collection with fetch type=lazy (fetchType=FetchType.LAZY) so that the collection elements are not fetched when the owning object is
you can used a Query with setFirstResult(..) and setMaxResults(..) in order to achieve paging. (and get rid of the collection then)

Related

Hibernate the effective way to persist parent-child data

I have the following entities and I would like to give some additional thoughts before I make a final decision.
Post
#Entity
public class Post {
#Id
#GeneratedValue
private long id;
private String author;
private String content;
private String title;
#OneToMany
private List<Comment> comments;
// Standard getters and setters...
}
And the entity, which holds child rows
#Entity
public class Comment {
#Id
#GeneratedValue
private long id;
private String author;
private String content;
#ManyToOne
private Post post;
// Standard getters and setters...
}
A post could have a big number of comments, the most of them of course are not changed during the user session. I would like to find out the best way to save data in the following scenarios:
1. Post data is not changed;
2. Post data is changed.
The standard way is to use the following code
Post saved = postRepository.save(post);
But is this approach the most effective when you have only one comment added or changed to the post? Should the approach be different here, namely remove the one to many relationship between Post and Comment entities and treat them separately? Also, I don't like the idea that a post object, which needs to be updated in the database, may contain a large number of comments, which in turn adds additional load on network.
First to make that work you need a cascade in the post entity else it will just update/save the Post entity
#OneToMany(cascade = CascadeType.ALL ,mappedBy = "post")
private List<Comment> comments;
Also hibernate works by dirty checking your entity.
Hibernate during the merge(update) will dirty check your managed entities and generate one update query just for the entities that you changed, so if you don't touch the Post entity and just update one Comment hibernate will generate one update query.
Also this phrase make no sense.
Also, I don't like the idea that a post object, which needs to be
updated in the database, may contain a large number of comments, which
in turn adds additional load on network.
The OneToMany relationship specified in Post is just for hibernate convenience and it's actually optional.
With that you define what is called a bi-directional relationship.
There is nothing in db except for the fk on Comment referencing Post

How to index a boolean #Field in Hibernate Search if the field is not in the db table

I have a problem with indexing the boolean #field in Hibernate Search, the problem is when the object has changed the rest of the fields are changed as well only the boolean field keeps the old state of the object.
#JsonIgnore
#Field(name = "isWarning", index = Index.YES)
#SortableField(forField = "isWarning")
private boolean isWarning() {
//some logic
}
what is the right way to approach this problem?
I assume this "logic" you mention accesses other entities. You need to tell Hibernate Search that those entities are included in the entity with the isWarning method.
Let's say the isWarning method is defined in an entity called MainEntity, and it accesses data from another entity called SomeOtherEntity.
In SomeOtherEntity, you will have the reverse side of the association:
public class SomeOtherEntity {
#ManyToOne // Or #OneToOne, or whatever
private MainEntity mainEntity;
}
Just add #ContainedIn and you should be good:
public class SomeOtherEntity {
#ManyToOne // Or #OneToOne, or whatever
#ContainedIn
private MainEntity mainEntity;
}
Note that, unfortunately, this can have a significant impact in terms of performance if SomeOtherEntity is frequently updated: Hibernate Search will not be aware of exactly which part of SomeOtherEntity is used in MainEntity, and thus will reindex MainEntity each time SomeOtherEntity changes, even if the changes in SomeOtherEntity don't affect the result of isWarning. A ticket has been filed to address this issue, but it's still pending.

Realm : How to structure one to many relationship

I have been looking over to many ORM's in android, by far what i have used and would fit to my app so far are ActiveAndroid and SugarOrm, but what i need is not currently supported(not supported but can be fix by creating sql scripts) as of now (one-to-many relationship). Im looking at Realm ORM for android a very promising one.
Is this possible with Realm?
// this is just a sample of what i need to do.,
// parent
class Message{
long id;
List<Meta> messages;
}
// child
class Meta{
long senderId;
String message;
Date date;
int status;
}
// I have already know how to do this on ActiveAndroid but seems a bit hard
// to update records or fetch single data.
Note: I have been having problems lately when manually creating my SQL scripts, and its very time consuming coding all of those when ORM's are there, And its very annoying when something needs to change I have to restructure most of the affected columns and etc.
I hope I had asked my question clearly and I hope there is a better way for this.
Thanks
Yes, that is very much possible with Realm. Realm is an object store, so it stores your objects as they are. In a normal object model one-to-many relationships are defined using lists, the same with Realm which has a special list called RealmList you can use.
In Realm the model you have should be defined as follow:
class Message extends RealmObject {
private long id;
private RealmList<Meta> messages;
// Getters and setters
}
class Meta extends RealmObject {
private long senderId;
private String message;
private Date date;
private int status;
// Getters and setters
}

object mapping when using Mongodb

I am new to mongo-db and i have few questions.
I have the following code:
public class User
{
private String id;
private String name;
private List<Order> orders;
}
public class Order
{
private String id;
private String orderName;
private Date orderDate;
}
What's the best persisting strategy for User object ?
should i create collection for both User and Order or just for User ?
should i save Order and then user ?
i am using spring data MongoRepository
Thank you.
I would consider how you're accessing the data when modeling. Some questions to ask yourself:
Do I need to get a user with his orders in one call?
How many orders are with a user on average? If it's a lot, maybe not best to denormalize user and orders.
How will my front end access this information? Will most calls to user even need orders? Will that information be too heavy/slow on the wire?
In general I would err on the side of denormalizing instead of the relational instinct to normalize. It's ok to have redundant data and to have inconsistent data.
Mongo doesn't do joins real time - at best you can do map/reduce.
The joining of data therefore either needs to be in the database (denormalized) or in the UI.

Hibernate joins every table in database

I've set up a small project as a test. I'm using BlazeDS and JPA with Hibernate on my test server, and flex with with dpHibernate to access the Java entities. Each Java entity extends BaseEntity, a class that contains ID and UUID fields. The Flex entities are created by DTO2FX.
My problem is that, when I run the Flex project to try and display a few rows from a Users entity, the SQL that is actually being executed is joining every table in my database. This continues until I get java.lang.StackOverflowError. This behavior is completely unexpected, and I'm not really sure where to look to fix the problem. Any suggestions would be greatly appreciated.
Clearly I've left out some details, but I'm hoping this gives a reasonable idea about the project. I would be more than happy to include any code that might be helpful, but I really have no idea what's causing the behavior at the moment. Thanks!
EDIT: Here is a mapping that might better explain the problem.
#Entity
#FXClass(ignoreSuperclasses={Principal.class, UserDetails.class})
#Table(name="edrUser")
public class User extends BaseEntity implements IAbstractEntity, Principal, UserDetails {
#Column(length=20)
private String username;
#ManyToMany(mappedBy="users",fetch=FetchType.LAZY)
private Set<Department> departments = new HashSet<Department>(0);
#ManyToOne
#JoinColumn(name="company_id",nullable=false)
private Company company;
#OneToMany(cascade=CascadeType.ALL, mappedBy="user", fetch=FetchType.LAZY)
private Set<DepartmentJobUserLink> departmentJobUsers = new HashSet<DepartmentJobUserLink>(0);
#Column(length=20)
private String password;
#Column(length=20)
private String forename;
public User(){
super();
}
/* Getters and setters */
}
Did you force lazy-loading to false?
Sounds to me like u having a cycle in your SQL tabledependencies, but thats just a guess. Checked that already?

Categories