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?
Related
I want to check if cert entity exist in the database using keys-only queries. So far I'm doing:
Iterable<Key<LikeMW>> liked = ofy().load().type(LikeMW.class).filter("likedObject", postKey).filter("user", userKey).keys();
post.setLiked(liked.iterator().hasNext());
So I have 2 questions:
1 - If I use ".first().now()" after ".keys()", does it switch from "keys-only" or it'll still be a "keys-only" query?
2 - Is there a better way to check if cert entity exist using "keys-only" queries and filter?
Thank you guys!
UPDATING
#Entity
public class LikeMW {
#Id
private Long id;
#JsonIgnore
#Index
#Load
private Ref<UserMW> user;
#JsonIgnore
#Index
private Key likedObject;
...
}
And one of possible liked objects...
#Entity
public class PostMW{
#Id
private Long id;
#JsonIgnore
#Load
private Ref<UserMW> owner;
#JsonIgnore
#Load
private Ref<MediaMW> media;
...
}
The only way to authoritatively look up whether an entity exists is to load it by key. You can certainly do a keys-only query, but it will be eventually consistent and will not guarantee that you do not create duplicates.
Given what you are trying to do, you will almost certainly be better off parenting LikeMW with the user and using the stringified likedObject as the string id. That way you can do a strongly consistent lookup and use transactions.
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
}
I am attempting to implement a Hibernate/JPA2 solution over an existing schema, which cannot be changed. Here is a minimal example of the existing schema:
CREATE TABLE REASON (
REASON_CODE CHAR(1),
REASON_DESCRIPTION CHAR(50))
CREATE TABLE HEADER (
REASON_CODE CHAR(1),
OTHERFIELD1 CHAR(40),
OTHERFIELD2 CHAR(40) )
Normally this would be the "correct" way from a DB perspective: Link REASON to HEADER by the REASON_CODE. However it's presenting me with an awkward problem in Java and I'm not sure of the best way to solve it. I've modeled these entities as follows:
#Entity
#Table(name="REASON")
public class Reason implements java.io.Serializable {
#Id
#Column(name="REASON_CODE", unique=true, nullable=false, length=1)
private Character reasonCode;
#Column(name="REASON_DESCRIPTION", nullable=false, length=25)
private String reasonDescription;
}
#Entity
#Table(name="HEADER")
public class Header implements java.io.Serializable {
#ManyToOne
#JoinColumn(name = "REASON_CODE", nullable = false)
private Reason reason;
#Column(name="OTHERFIELD1")
private String otherField1;
#Column(name="OTHERFIELD2")
private String otherField2;
}
Once again, as far as I can tell, this is "correct" from a Java perspective - linking Header to Reason with a reference.
The problem is that when I need to use one of these Reason values in my code I wind up with awkward syntax like:
Reason r = reasonService.findOne('X'); // X is the REASON_CODE in the database record
// Do some processing with variable r
Or this:
header.setReason(reasonService.findOne('X'));
Ideally I could implement Reason as an enum like:
public enum Reason {
X_MARKSTHESPOT("X"),
C_MEANSSOMETHINGELSE("C"),
F_MEANSATHIRDTHING("F") ;
private String code;
private Reason(String code) {
this.code = code;
}
}
And then simply have this in my code:
header.setReason(Reason.X_MARKSTHESPOT);
But from what I understand that is not possible with JPA, which offers only EnumType.STRING (basically the name) or EnumType.ORDINAL (even worse, the index in the enum list). A possible way around this would be JPA 2.1's Converter, but I have never used it. I have also read here (in one of the answers) that a Hibernate User Type might be useful. One of our programmers has solved this in another app by writing two complete classes - an enum class for internal use and a "shadow" class which iterates through the enum and syncs the records in the database on every startup. But this seems like a kludgey way to do it. What is the best way to handle this, bearing in mind that the database schema cannot be changed?
What is appropriate way of creating objects with One-to-Many relationship using Objectify and RequestFactory? I've read documentation for these libraries, and also reviewed number of sample projects such as listwidget and gwtgae2011. All of them use #Embedded annotation which is not what I want because it stores everything within one entity. Another option according to documentation would be to use #Parent property in child classes. In my example (getters/setters removed for simplicity) I have entities Person and Organization which defined as
#Entity
public class Person extends DatastoreObject
{
private String name;
private String phoneNumber;
private String email;
#Parent private Key<Organization> organizationKey;
}
and
#Entity
public class Organization extends DatastoreObject
{
private String name;
private List<Person> contactPeople;
private String address;
}
Now if I understood documentation correctly in order to persist Organization with one Person I have to persist Organization first, then set organizationKey to ObjectifyService.factory().getKey(organization) for Person object and then persist it. I already don't like that I have to iterate through every child object manually but using RequestFactory makes everything is more convoluted due to presence of proxy classes. How would I define Organization and OrganizationProxy classes - with Key<> or without it ? Will I have to define something like this in Organization ?
public void setContactPeople(List<Person> contactPeople)
{
for (int i = 0; i < contactPeople.size(); ++i)
{
DAOBase dao = new DAOBase();
Key<Organization> key = dao.ofy().put(this);
contactPeople.get(i).setOrganizationKey(key);
}
this.contactPeople = contactPeople;
}
And how would I load Organization with its children from Datastore ? Will I have to manually fetch every Person and fill out Organization.contactPeople in #PostLoad method ?
It seems like I'll have to write A LOT of maintenance code just to do what JPA/JDO does behind the scene. I simply don't get it :(
Am I missing something or it's the only way to implement it ?
Thanks a lot for answers in advance!!!
You need to make it as #Parent only when you going to use it in transaction against all Person in this Organization. I'm sure it's not what you want.
It's enough to save just private Key<Organization> organizationKey, and filter by this field when you need to find Person for specified Organization
As about loading all referenced objects - yes, it is, you have to load it manually. It's pita, but it's not a lot of code.
Also, there is a different way to store this relationship, if your organization are small enough, and consists of few hundreds of people. At this case you can have List<Key<Person>> contactPeopleKey;, and load all this people by existing Key, manually, it much be much faster than loading by new Query
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)