Apache Ignite : Lazy References - java

Don't know how to properly formulate the title, but here is the problem.
Let's say I have a class Person and a class Organization and their association type is Many to One. In Java code Person object has a reference to Organization object and Organization has a Collection of Person objects. Both Person and Organization objects are Serializable. In addition to that I have programmed Person in such a way that it is affinity collocated with Organization.
If I put an instance of Person object into the cache (grid node) I would like to serialize only identifier of associated Organization, but not the whole object that is being referenced.
Is there any solution out of the box (some kind of proxy) that will skip serialization of associated object and will lazy load the associated object by identifier on a deserialized instance of Person?
I have already seen a custom solution for Oracle Coherence grid that is based on decorators, but the implementation is extremely complex.

How about storing an ID of an organization instead of the whole Organization object? This is the proper way to collocate people with their organizations.
If you need to store an actual Organization object inside of a Person instance, you may make a transient field and update it lazily, when you access it. Something like this:
class Person {
#AffinityKeyMapped
private int orgId;
private transient Organization org;
// Other fields, constructors, getter, setters.
}
// ...
// Accessor method in DAO logic.
Organization getOrganization(Person person, IgniteCache<Integer, Organization> orgCache) {
Organization org = person.getOrganization();
if (org == null) {
org = orgCache.get(person.getOrganizationId());
person.setOrganization(org);
}
return org;
}
This way org field won't be serialized, when Person is put into Ignite cache. Only orgId will be. And Organization will be requested from cache only once for a Person object. Subsequent calls to getOrganization() will use a saved value.

Related

Wicket - Serialization of persisted and non-persisted JPA entities

I know that when using Wicket with JPA frameworks it is not advisable to serialize entities that have already been persisted to the database (because of problems with lazy fields and to save space). In such cases we are supposed to use LoadableDetachableModel. But what about the following use-case?
Suppose we want to create a new entity (say, a Contract) which will consist, among other things, of persisted entities (say, a Client which is selected from a list of clients stored in the DB). The entity under creation is a model object of some Wicket component (say, a Wizard). In the end (when we finish our wizard) we save the new entity to the DB. So my question is: what is the best generic solution to the serialization problem of such model objects? We can't use LDM because the entity is not in the DB yet but we don't want our inner entities (like Client) to be serialized wholly, too.
My idea was to implement a custom wicket serializer that checks if the object is an entity and if it is persisted. If so, store only its id, otherwise use the default serialization. Similarly, when deserializing use the stored id and get the entity from the DB or deserialize using the default mechanism. Not sure, though, how to do that in a generic way. My next thought was that if we can do it, then we do not need any LDM anymore, we can just store all our entities in simple org.apache.wicket.model.Model models and our serialization logic will take care of them, right?
Here's some code:
#Entity
Client {
String clientName;
#ManyToOne(fetch = FetchType.LAZY)
ClientGroup group;
}
#Entity
Contract {
Date date;
#ManyToOne(fetch = FetchType.LAZY)
Client client;
}
ContractWizard extends Wizard {
ContractWizard(String markupId, IModel<Contract> model) {
super(markupId);
setDefaultModel(model);
}
}
Contract contract = DAO.createEntity(Contract.class);
ContractWizard wizard = new ContractWizard("wizard", ?);
How to pass the contract? If we just say Model.of(contract) the whole contract will be serialized along with inner client (and it can be big), moreover if we access contract.client.group after deserialization we can bump into the problem: https://en.wikibooks.org/wiki/Java_Persistence/Relationships#Serialization.2C_and_Detaching
So I wonder how people go about solving such issues, I'm sure it's a fairly common problem.
I guess there are 2 approaches to your problem:
a.) Only save the stuff the user actually sees in Models. In your example that might be "contractStartDate", "contractEndDate", List of clientIds. That's the main approach if you don't want your DatabaseObjects in your view.
b.) Write your own LoadableDetachableModel and make sure you only serialize transient objects. For example like: (assuming that any negative id is not saved to the database)
public class MyLoadableDetachableModel extends LoadableDetachableModel {
private Object myObject;
private Integer id;
public MyLoadableDetachableModel(Object myObject) {
this.myObject = myObject;
this.id = myObject.getId();
}
#Override
protected Object load() {
if (id < 0) {
return myObject;
}
return myObjectDao.getMyObjectById(id);
}
#Override
protected void onDetach() {
super.onDetach();
id = myObject.getId();
if (id >= 0) {
myObject = null;
}
}
}
The downfall of this is that you'll have to make your DatabaseObjects Serializable which is not really ideal and can lead to all kind of problems. You would also need to decouple the references to other entities from the transient object by using a ListModel.
Having worked with both approaches I personally prefer the first. From my expierence the whole injecting dao objects into wicket can lead to disaster. :) I would only use this in view-only projects that aren't too big.
Most projects I know of just accept serializing referenced entities (e.g. your Clients) along with the edited entity (Contract).
Using conversations (keeping a Hibernate/JPA session open over several requests) is a nice alternative for applications with complex entity relations:
The Hibernate session and its entities is kept separate from the page and is never serialized. The component just keeps an identifier to fetch its conversation.

Safe embedded entity with objectify

I have two entities.
#Entity
public class Recipe {
#Id
private Long id;
private List<Step> steps;
}
#Entity
public class Step {
#Id
private Long id;
private String instruction;
}
And the following Clound Endpoint
#ApiMethod(
name = "insert",
path = "recipe",
httpMethod = ApiMethod.HttpMethod.POST)
public Recipe insert(Recipe recipe) {
ofy().save().entities(recipe.getSteps()).now(); //superfluous?
ofy().save().entity(recipe).now();
logger.info("Created Recipe with ID: " + recipe.getId());
return ofy().load().entity(recipe).now();
}
I'm wondering how do I skip the step where I have to save the emebedded entity first. The Id of neither entity is set. I want objectify to automatically create those. But if don't save the embedded entity I get an exception.
com.googlecode.objectify.SaveException: Error saving com.devmoon.meadule.backend.entities.Recipe#59e4ff19: You cannot create a Key for an object with a null #Id. Object was com.devmoon.meadule.backend.entities.Step#589a3afb
Since my object structure will get a lot more complex, I need to find a way to skip this manual step.
I presume you are trying to create real embedded objects, not separate objects stored in the datastore and linked. Your extra save() is actually saving separate entities. You don't want that.
You have two options:
Don't give your embedded object an id. Don't give it #Entity and don't give it an id field (or at least eliminate #Id). It's just a POJO. 90% of the time, this is what people want with embedded objects.
Allocate the id yourself with the allocator, typically in your (non-default) constructor.
Assuming you want a true embedded entity with a real key, #2 is probably what you should use. Keep in mind that this key is somewhat whimsical since you can't actually load it; only the container object can be looked up in the datastore.
I suggest going one step further and never use automatic id generation for any entities ever. Always use the allocator in the (non-default) constructor of your entities. This ensures that entities always have a valid, stable id. If you always allocate the id before a transaction start, it fixes duplicate entities that can be created when a transaction gets retried. Populating null ids is just a bad idea all around and really should not have been added to GAE.
The concept of the embedded is that the embedded content is persisted inside the main entity.
Is this the behaviour you are trying to configure?
The default behaviour of a Collection (List) of #Entity annoted class is to refer them instead of embed them. As you current configuration, the List<Step> variable does not have any annotation to override the default configuration, which is a different entity related to another one.
The error you are getting is because Objectify, when it saves the recipe entity, is trying to get the key of each step to create the relationship (and save them in the recipe entity), but if the entity step is not saved yet on the datastore, does not have a key
If you are trying to persist the steps inside the recipe entity, you need to setup objectify like this
#Entity
public class Recipe {
#Id
private Long id;
private List<Step> steps;
}
public class Step {
private Long id;
private String instruction;
}
As you can see, I removed the #Id annotation (an embedded Entity does not require an ID because is inside another entity) and the #Entity from the Step class. With this configuration, Objectify save the step entities inside the recipe entity
Source: https://code.google.com/p/objectify-appengine/wiki/Entities#Embedded_Object_Native_Representation

What does the Hibernate proxy object contain?

All I could gather from Google is that:
Hibernate uses a proxy object to implement lazy loading.
When we request to load the Object from the database, and the fetched Object has a reference to another concrete object, Hibernate returns a proxy instead of the concrete associated object.
Hibernate creates a proxy object using bytecode instrumentation (provided by javassist). Hibernate creates a subclass of our entity class at runtime using the code generation library and replaces the actual object with the newly created proxy.
So, what exactly does the Proxy object contain?
Does it contain a skeleton object reference object with only the id field set? Others field will be set when we call the get method?
Does the Proxy object contain the JDBC statement to fetch all data required to fully populate the referenced object.
Is there something else I might be missing?
I am not asking for spoon feeding but if you can provide any link with information that would be great.
Any correction to above description will also be welcomed.
Example.
class Address {
String city;
String country;
}
class Person{
int id;
String name;
Address address;
}
When we try to load the Person object, Hibernate will subclass Person class like:
class ProxyPerson extends Person {
int id;
String name;
Address proxyCGLIBObject;
}
and return a ProxyPerson object. Object of ProxyPerson will have a value for id and name but proxy for Address.
Am I correct?
What can I expect from adding a toString() method on the proxy object?
The Hibernate Proxy is used to substitute an actual entity POJO (Plain Old Java Object).
The Proxy class is generated at runtime and it extends the original entity class.
Hibernate uses Proxy objects for entities is for to allow [lazy loading][1].
When accessing basic properties on the Proxy, it simply delegates the call to the original entity.
Every List, Set, Map type in the entity class is substituted by a PersistentList, PersistentSet, PersistentMap. These classes are responsible for intercepting a call to an uninitialized collection.
The Proxy doesn't issue any SQL statement. It simply triggers an InitializeCollectionEvent, which is handled by the associated listener, that knows which initialization query to issue (depends on the configured fetch plan).

(Spring / Hibernate) Initialize children objects strategy

I have a form that should be bind to a complex object that wrap a lot of children, every time before loading this form I have to initialize all children object in a method that only have a lot of new statements and calling a setter method, I have to repeat this scenario for a lot of forms and other complex objects
Is there a better strategy than the initializeEmployee method?
For example:
#Entity
public class Employee {
Integer Id;
Contract contract;
Name name;
List<Certificate> list;
// getter and setters
}
#Entity
public class Contract {
String telephoneNum;
String email;
Address address;
// getter and setters
}
#Entity
public class Address {
String streetName;
String streetNum;
String city;
}
public class Name {
String fName;
String mName;
String lName;
// getter and setters
}
// And another class for certificates
public initializeEmployee() {
Employee emplyee = new Employee();
Name name = new Name();
employee.setName(name);
Contract contract = new Contract();
Address address = new Address();
contract.setAddress(address);
employee.setContract(contract);
// set all other employee inner objects,
}
EDIT:
According to below answers, it seems that there is no optimal answer. However, I could use the Entity constructor or a Factory Design Pattern.
But both solutions don't solve my other problem in initializing all fields strategy with Required and Optional fields.
For example:
If I have Name as required (i.e. the Employee entity will not persisted if Name object attributes are empty, on the other side the Contract entity is an optional. and I cannot persist an empty Contract object to the database, so I have to make it null first before persistence, then reinitialize it after persistence like the following
// Set Contract to null if its attributes are empty
Contract contract = employee.getContract()
if(contract.getTelephoneNum().isEmpty && contract.getEmail().isEmpty() && contract.getAddress().isEmpty()){
empolyee.setContract(null);
}
employeeDAO.persist(employee);
// reinitialize the object so it could binded if the the user edit the fields.
employee.setContract(new Contract());
You can add constructors (it is their role after all) to your entities to instanciate these fields if having a null value has no meaning for your case.
Another way, if you don't like adding contructors, is to add a static factory method to instanciate your bean which will look like initializeEmployee() but with potential parameters and returning an Employee object. http://en.wikipedia.org/wiki/Factory_method_pattern
Similarly, you can instanciate your collections too, as there is probably no meaning for a null collection (but there is one for an empty collection).
You can add behaviour to your entities, don't be locked in Anemic Domain Model which is considered an anti-pattern by Martin Fowler http://www.martinfowler.com/bliki/AnemicDomainModel.html
EDIT
I see you are using dao.persist(entity): you are probably using JPA. If so, maybe it is best to not modify your object graph (on the front side) and add an EntityListener (in the persistence layer) for Employee: here is a link for Hibernate EntityListener (it is a JPA feature, so if you are using another framework don't worry) http://docs.jboss.org/hibernate/entitymanager/3.5/reference/en/html/listeners.html
With an EntityListener, you can add small "aop like" actions before persistence and after. This will allow you to not deal with null values on the domain and front layers and will ensure that every entity fits in any case (better validation).
In PrePersist: you'all add your code to check null values (possibly with custom methods "isEmpty()" on the domain classes) and nullify fields if needed. In PostPersist you add your new object.
I couldn't get what you really need, but I think you could try this way:
#Entity
public class Employee {
Integer Id;
Contract contract = new Contract();
Name name = new Name();
List<Certificate> list;
// getter and setters
}
#Entity
public class Contract {
String telephoneNum;
String email;
Address address = new Address();
// getter and setters
}
I'm not sure it reduces the verbosity at all but since this is a UI issue, you could initialize the editable objects in your flow.xml and then put it all together in an Employee instance prior to saving to the DB.
<on-start>
<evaluate expression="new foo.bar.Name()" result="flowScope.employeeName" />
<evaluate expression="new foo.bar.Contract()" result="flowScope.contract" />
<evaluate expression="new foo.bar.Address()" result="flowScope.address" />
</on-start>
Actually I would advise against using Hibernate Entities directly in GUI. In many cases (I assume in yours too, but I'm missing some details on your use-case) it is useful to use a Data Transfer Object pattern instead. You can create such DTO that is GUI specific, has only those fields that you need, and the structure is only as complex as needed.
After specific user action (like save e.g.) use those DTOs (on event handling) to create your Entities that will be persisted.
Unless your case is that just entering the GUI screen causes Entities creation, then I would recommend Factory pattern.
Also note that in many cases initialization of component objects that are making up the main object (Employee in your example) are better to be initialized in constructor of main object, eg. if you expect that Contract cannot be null - initialize it in constructor. The same for the list of Certificates and others.

Can I persist child objects in #PrePersist handler of a parent class? (Objectify 3.1b1)

I am new to Objectify and trying to implement One-to-Many relationship. I have entities Organization and entity Person. Organization has #Transient property List< Person > contactPeople. Class Person has #Parent property Key< Organization > organizationKey which I can set via setter.
I'd like to persist contactPeople in #PrePersist handler of Organization. In order to do that I need to set parent key in Person.
Wiki here says: "You can't update #Id or #Parent fields in a #PrePersist callback; by this time, the low-level Entity has already been constructed with a complete Key so it can be passed in as an optional parameter."
I'm not sure this is still accurate information ? Because key of com.google.appengine.api.datastore.Entity object that I get in PrePersist handler has key that literally says "no-id-yet".
How would you implement this ?
Thank you!
Update at Nov 17, 2011:
In new Objectify4 we'll be able to do semi-automatic relationships like this:
class Beastie {
#Parent
#Load
ParentThing parent;
#Id Long id;
#Load({"bigGroup", "smallGroup"})
SomeThing some;
#Load("bigGroup")
List<OtherThing> others;
#Load
Ref<OtherThing> refToOtherThing;
Ref<OtherThing> anotherRef; // this one is never fetched automatically
}
Here is evolving design document of new version.
This is big news. Twig author, John Patterson, joined Objectify project today.
Hm, seems that you need to make an Dao in front of your data models. So, you will able to do something like:
Organization organization = ...
List<Person> people = ...
ob.put(organization)
for (Person person: people) {
person.organizationKey = organization.getKey();
ob.put(person);
organization.contactPeopleKeys.add(person.getKey());
}
ob.put(organization)
GAE+Objectify requires a lot of thing to handle by your own code, so it's a common thing

Categories

Resources