How to make a bidirectional one-to-one relation by GreenDAO? - java

I use ORM GreenDAO for DAL layer of my Android app. I've a problem in one to one relation between two tables. for example:
Entity page = schema.addEntity("Page");
Entity bookmark = schema.addEntity("Bookmark");
Property pageIdProperty = bookmark.addLongProperty("pageId").getProperty();
bookmark.addToOne(page, pageIdProperty); // any bookmark related to a page
page.addToOne(bookmark, pageIdProperty); // any page can has a bookmark
Is this relation mistake?
When I define it, I can't call page.getBookmark() in the Page Class
If this is true, Does any way I can make it bidirectional for one to one relationship?

First off, good use cases for one-to-one relations are rare. Are you sure that it's not a one-to-many? If you still think it's a one-to-one: does it make sense to merge both entities into one?
Besides that, bookmark.addToOne(page, pageIdProperty) is fine, while page.addToOne(bookmark, pageIdProperty) does not work. To-one relations require the id property to be in the same entity. To-many would work this way, check the documentation on relation for details.

Best workaround so far is to use the addToOne on the entity where the foreign key exists and addToMany on the other side. It is not terribly inconvenient as you only have to make sure that you add one object to the list.

You have several errors. First you need to create a PK before FK property on bookmark.
Try this:
Entity page = schema.addEntity("Page");
Entity bookmark = schema.addEntity("Bookmark");
bookmark.addLongProperty("bookmarkId").primaryKey().autoincrement();
Property fkPage = bookmark.addLongProperty("pageId").getProperty();
bookmark.addToOne(page, fkPage).setName("page");
Do the same steps for Page entity.

Related

Hibernate manyToOne filter on base entity

I have an entity "Event" that has a ManyToOne relationship with the entity "Organization". So an Organization can have multiple events.
What I originally wanted to do was to filter the entity Event using a property of the Organization entity. So basically when I fetch events, only return the events that have an Organization.code= :codeParam.
To accomplish that I implemented a hibernate filter with :
#FilterDef(name="codeFilter", parameters=#ParamDef( name="codeParam", type="string" ) )
...
#ManyToOne
#JoinColumn(name="Organization_Id")
#Filter(name="codeFilter", condition=" code = :codeParam")
private Organization organization;
...
Filter hibernateFilter = sess.enableFilter("codeFilter");
hibernateFilter.setParameter("codeParam", "hola");
Unfortunately according to a post from the Hibernate Team on the hibernate forums, this is not possible :
A Hibernate data filter does not change the multiplicity of an association. By definition it therefore does not filter many-to-one, one-to-one, or any load() or get() operation.
What is it supposed to do, return NULL instead of an instance? NULL does not mean FILTERED, it means NULL. You guys are using filters wrong.
So my question is : is there any way to filter the base entity ("Event") with a condition on the entity from a manyToOne relationship (Organization.code= :codeParam)?
I need this to be enforced every time there is a fetch of events, so a solution using the already existing hibernate filters or something similar would be greatly appreciated.
EDIT1: The question is a simple example of what needs to be done on a significantly bigger scale. Basically, we want to add security to all our Entities and their own nested Entities through the use of a globally defined filter on a Unix permissions row that all our tables have.
WARNING: Do not do this, it is dependent on Hibernate internals and prone to breaking on schema changes, and possibly on variations in individual query setup.
Set Hibernate to show its generated sql, run the query you want to filter (in this case, loading some Event objects), and check what name it assigns to the join used for fetching the related Organization. For example, the generated sql might include inner join Organization someNameHere on this_.Organization_Id = someNameHere.OrganizationId. Then apply the filter, not to the association, but to the Event class, with condition "someNameHere.code = :codeParam".
This is, unfortunately, the only way I've been able to find to filter one class by the properties of an associated class.
I'm trying to make a more robust solution, but it's a complex issue and I'm still in the research stage for that. I expect it will use code generation (through an annotation processor) and programmatic modification of Hibernate's mapping information on startup, but I'm not sure what else yet.

Eager loading despite Lazy Initialization?

we have an entity that has a lot of ManyToOne, OneToOne, etc relations which themself have again some relations.
For example
#OneToMany(targetEntity = Season.class, cascade = {
CascadeType.ALL
})
#JoinColumn(name = "SEASON_ID")
public List<Season> getSeasons(){...}
(I can not change this).
Those are loaded lazily (by default I think) which is good and we don’t want to change this.
Now we have this one case, where we want to find the whole entity eagerly by it's id to return it.
I found a lot of suggestions to change the entity and discussions about wether eager or lazy loading is better, which do not help me at this point, since the entity is out of reach for us.
Is there a way to do this, without changing the entity and without having to call every possible getter to initialize the lazy entities (because those are too many)?
So for example, the answer to Question 24573877 does not work for me.
Basically I want to say "load the entity eagerly, but just this once".
Currently I'm just doing return em.find(MyEntity.class, contractId) (I could change this).
Thanks and regards
Urr4
look at : http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/queryhql.html
chapter : 14.3. Associations and joins
A "fetch" join allows associations or collections of values to be initialized along with their parent objects using a single select. This is particularly useful in the case of a collection. It effectively overrides the outer join and lazy declarations of the mapping file for associations and collections. See Section 19.1, “Fetching strategies” for more information.
You've to write your query instead of use em.find.
exemple this query :
from Cat as cat
inner join fetch cat.mate
left join fetch cat.kittens
will return cat with mate and kittens already loaded (eager), even if they have been initialized in lazy
Edit :
Or you can use fetch profil :
In order to mitigate these, Hibernate propose a fetch strategy that works not on the mapping level, but on the request level. Thus, you can still have lazy loading mappings but eager fetching in some cases.
look at : https://blog.frankel.ch/hibernate-hard-facts-part-6
I didn't really solve it the way i wanted to, but it works now.
It seems, there really is no way to eagerly load an entity, you know nothing about.
Our problem was, that the entity came from a 3rd-party Maven dependency and was unchangeable and hard to look into.
In the end we build an entityProcessor, that took the lazily loaded entity and called every getter and all the getters of the child entities recursively.
If we have control over an entity, i will use FetchProfiles next time, otherwise, I'd recommend implementing a clone() function.

Maintaining relationships in JPA 2.0

I've been using JPA 2.0 for a while but, sad to admit, I haven't had enough time to learn it properly. It seems like I lack the basics of how to work with Entity Manager.
Moving one step at a time, I'd like to first ask you about maintaining relationships between mapped entities. Of course I know how to create mappings between entities, different types of available associations (OneToOne, etc.) and how databases work in general. I'm purely focused on maintaining it via Entity Manager, so please do not send me to any kind of general knowledge tutorial :-).
The questions are:
Am I right that as a programmer I'm responsible for maintaining (creating/updating/removing) relationships between instances of entities?
Do I have to always update (set to null, remove from collection, etc.) instances by hand?
Plain SQL can set entities to NULL on deleting, but it seems like JPA can't do such a simple thing. It also seems like a burden to do it manually. Is there a way to achieve that with JPA?
If I have OneToMany relationship and set to NULL the entity on the Many side of the relationship. Then I persist the changes in a Set by saving the entity on the One side. Do I then have to update the entities in the Many side and set association to NULL in each instance? Seems pure silliness for one-directional bindings!
Thanks in advance!
The main thing you need to investigate is the different options you have when mapping on entity. For example in the next piece of code the cascade all option will instruct jpa to delete the child list when the parent is deleted.
#OneToMany(fetch = FetchType.LAZY, cascade = { CascadeType.ALL }, mappedBy = "parent")
private Set<Child> events = new HashSet<Child>();
Yes. You maintain the object tree and modify it to look like what
you want.
Yes and no. If you want the entity to reference null, then yes.
For instance, if you are removing one Entity, then you should clean
up any references to it held by other entities that you are not
removing. A practical example: its good practice to let an Employee
know his/her Manager has been let go. If the Employee is going to
stay, it should either have its manager reference nulled out or set
to a different manager, before the current manager can be removed.
If the employee is going to be removed as well, then cascade remove
can cascade to all the Manager's subordinates, in which case you do
not need to clean up their references to the manager - as they are
going away too.
I don't quite understand what SQL is setting to null. Deleting
removes the row in the database, so there isn't anything to set to
null. Cleaning up a reference shouldn't be that difficult in the
object model, as JPA has a number of events to help such as
preremove preupdate etc. In the end though, the problem is with
your java objects. They are just java objects, so if you want
something done, your application will need to do it for the most
part. JPA handles building them and pushing them to the database,
not changing the state for you.
Yes and no. If you set up a bidirectional relationship, you must
maintain both sides as mentioned above. If you set the child's
parent reference to null, you should let the parent know it no
longer has a child, wouldn't you? Your parent will continue to
reference its child for as long as that Parent instance exists. So
even though the database is updated/controlled through the side that
owns a relationship, the object model will be out of synch with the
database until it is refreshed or somehow reloaded. JPA allows for
multiple levels of caching, so it all depends on your provider setup
how long that Parent instance will exist referencing a Child that no
longer exists in the database.

How to model relationship between different parent entities and one common child entity

I'm looking for some suggestions for best practices around modeling the relationship between various entities and their documents (binaries such as PDF, TIFF etc). The entities are standard JPA/Hibernate stored in a PostgreSQL database. The documents themselves will be stored in MongoDb database.
The plan is to create a child entity to represent the document, which contains the id to the binary data to retrieve it as needed. But what would the relationship be?
If I simply created one if these document entities for each parent entity then a simple one to many relationship would work, but that seems to redundant.
I could simply put a "type" column that indicates which entity the document belongs to, and then query the document table with a named query of "id = ? and type = ?". I guess that would work, but there is something about that I'm not crazy about either - just can't put my finger on it :) Maybe that's just fine.
Another option I have looked at (although I admit I have never used it before, and would need to study it a bit more) is to use a unidirectional one to many with join table. However, I don't think this will work either since there is no guarantee that there wouldn't be duplicate parent keys. I use a single sequence for all basic relation tables primary keys, which should guarantee it, but it still doesn't sound like a good idea.
Finally, I have considered whether I create an entity and then extend it for each parent entity, but I think that would have the same flaw - the theoretical existence of non-unique parent ids.
Before I make a final decision, I'd like to see what other suggestions the community might have to offer.
Thanks in advance for your ideas.
If I simply created one if these document entities for each parent entity then a simple one to many relationship would work, but that seems to redundant.
I'm a bit confused. If you create a document for each parent, isn't that one-to-one and not one-to-many? It sounds like you want a one-to-many relationship. In which case, you would only create a single document for all parent entities that reference it.

How to avoid Lazy fetch, even when it is set to lazy fetch mode and ecrypt/decrypt column.....?

I have one to many association in my dto,
Parent DTO : Question
Child DTO : History
Question 1:
Means One question record has many history records, I am using JPA2.x with hibernate,
I bound the entities with lazy fetching method/mode. some places I want the lazy fetching...
and some places I don't want the lazy fetching not even egar. Means I don't want the data collection itself. I need only the parent class list, even if I call getHistories() method, it should not do lazy fetch in few places.... How to use entityManager to avoid lazy fetching.....even though the collection was set to lazy fetch mode.....?
Question 2:
I need to encrypt the question using mysql encode/decode functions. when inserting encrypt the value and save. when selecting decode the content.....
Solution can be in mapping or criteria query...?
Thanks In Advance....!
Question 1:
Your requirement makes no sense. If you don't want to access the history, don't call getHistories(). If you access the collection of History, either your Question is attached, and the collection will be loaded, or it's detached, and you'll get a lazy loading exception.
Question 2:
See http://docs.jboss.org/hibernate/core/3.6/javadocs/org/hibernate/annotations/ColumnTransformer.html. The example in the javadoc is precisely what you want to do.
For question 1, you need to do two things,
If you want your parent-child entities to be selected 'lazily', then annotate the bir-directional fields with fetch = lazy. This should work well in the hibernate session, as long as you dont load or 'touch' one of the lazy loaded fields.
If you want your parent-child entities to be selected 'eagerly', then anotate the fields in the bi-directional association as fetch = eager.
If you want 'some places I don't want the lazy fetching not even egar', then you have to decide at code time, whether to have a relationship between the parent-child entity, if you don't, then just dont map the bi-directional association. You CAN create more than one entity class to map different assoications, even entities with no association.

Categories