Spring Data NEO4J: relations have null values - spring

I have a spring 3.1 (Milestone) and Spring Data Neo4J 2.1 RC project running set up. All starts up properly and the neo4j database is being populated as desired, also visible in neoclipse.
Now I fetch an entity (lets call it Container.java) by id and have the relation "Event".
The relation in Container.java is modelled as follows:
#RelatedTo(type="HAS_EVENTS", direction = Direction.BOTH)
Set<Event> events = new HashSet<Event>();
When I access container.getEvents() and iterate over them, I can see that the single event has an id, but all other properties are null :(
When having a look with neoclipse, all properties are saved as they should be.
Is there some kind of "eager" or "lazy" loading? I do not use a #RelationshipType.

One night spent: I have to add the #Fetch entity. Makes sense from my point of view, as if there was eagerly loading enabled, I could easily generate cycles :)

#Fetch entity is for eager loading
for lazy loading ,you can use neo4jTemplate.fetch method template.fetch(Event.getEvents())

Related

Spring data JPA save() return less/incorrect child and parent association mapping fields [duplicate]

I'm developing a RESTful webservice with spring-data as its data access layer, backed by JPA/Hibernate.
It is very common to have relationships between domain entities. For example, imagine an entity Product which has a Category entity.
Now, when the client POSTs a Product representation to a JAX-RS method. That method is annotated with #Transactional to wrap every repository operation in a transaction. Of course, the client only sends the id of an already existing Category, not the whole representation, just a reference (the foreign key).
In that method, if I do this:
entity = repository.save(entity);
the variable entity now has a Category with only the id field set. This didn't surprise me. I wasn't expecting a save (SQL insert) to retrieve information on related objects. But I need the whole Product object and related entities to be able to return to the user.
Then I did this:
entity = repository.save(entity);
entity = repository.findOne(entity.getId());
that is, retrieve the object after persisting it, within the same transaction/session.
To my surprise, the variable entity didn't change anything. Actually, the database didn't even get a single select query.
This is related with Hibernate's cache. For some reason, when in the same transaction, a find does not retrieve the whole object graph if that object was previously persisted.
With Hibernate, the solution appears to be to use session.refresh(entity) (see this and this). Makes sense.
But how can I achieve this with spring data?
I would like to avoid to create repetitive custom repositories. I think that this functionality should be a part of spring data itslef (Some people already reported this in spring data's forum: thread1, thread2).
tl;dr
References between entities in the web layer need to be made explicit by using links and should not be hidden behind semi-populated object instances. References in the persistence layer are represented by object references. So there should be a dedicated step transforming one (the link) into the other (the fully populated object reference).
Details
It's an anti-pattern to hand around backend ids as such and assume the marshaling binding doing the right thing. So the clients should rather work with links and hand those to the server to indicate they want to establish a connection between an already existing resource and one about to be created.
So assuming you have the existing Category exposed via /categories/4711, you could post to your server:
POST /products
{ links : [ { rel : "category", href : "/categories/4711" } ],
// further product data
}
The server would the instantiate a new Product instance, populate it with additional data and eventually populate the associations as follows:
Identify properties to be populated by looking up the link relation types (e.g. the category property here.
Extract the backend identifier from the given URI
Use the according repository to lookup the related entity instance
Set it on the root entity
So in your example boiling down to:
Product product = new Product();
// populate primitive properties
product.setCategory(categoryRepository.findOne(4711));
productRepository.save(product);
Simply posting something like this to the server:
POST /products
{ category : {
id : 1, … },
…
}
is suboptimal for a lot of reasons:
You want the persistence provider to implicitly persist a Product instance and at the same time 'recognize' that the Category instance referred to (actually consisting of an id only) is not meant to be persisted but updated with the data of the already existing Category? That's quite a bit of magic I'd argue.
You essentially impose the data structure you use to POST to the server to the persistence layer by expecting it to transparently deal with the way you decided to do POSTs. That's not a responsibility of the persistence layer but the web layer. The whole purpose of a web layer is to mitigate between the characteristics of an HTTP based protocol using representations and links to a backend service.

Hibernate to initialize object in a different transaction

I got the famous LazyInitializationException.
I have an object User which is stored in the session. This object contains an other object Market which is lazy initialized.
When I load the user in the session, I don't load Market because it is too heavy and I don't need it everytime.
When I want to load the market, I am in a different transaction and I don't want to reload the user from the database. How can I retrieve the Market object? Knowing that User.market contains the Hibernate proxy and so the id of the market and that I don't want to hack Hibernate using reflection.
That would be even better if I could load the market without loading it into the user. Since the user is in the session, I don't want to put a lot of stuff in the session.
A JPA compatible solution would be even better.
Cheers
If the eager mode fetching is not acceptable, and if the transaction cannot be maintained up to the Market retrieval, a specific dao method could be implemented to retrieve specifically the market from a user
public List<Market> retrieveMarketFromUser (final User user) {
Query query = session.createQuery("SELECT m FROM User AS u INNER JOIN u.market as m WHERE u.userid = :uid");
query.setParameter("uid", user.getId());
List<Market> list = query.list();
return list;
}
or the short version
Query query = session.createQuery("SELECT u.market FROM User AS u WHERE u.userid = :uid");
This is maybe not the JPA solution you were expecting, just a workaround.
What you have to do is to annotate the accessors instead of the fields. This will allow you to avoid loading of the market object when you initially load the user, but you will have access to the id of the market from the Hibernate proxy object without triggering a lazy loading or getting a LazyInitializationException. Then later on when you want to load the market itself you do a normal entity retrieval based on its id. You can read a detailed explanation of how this works here.
If the relation is bidirectional then you can load the Market independently using a query with clause like where market.user.id = ?.
Why is the obvious solution not good? Like the one ring0 suggested, or simply using the findById or find methods if you already have the id in the User object.
//if using a session factory
session.findById(Market.class, marketId);
//if using the EntityManager
em.find(Market.class, marketId);
Depending on how the current_session_context_class configured (I have it in hibernate.cfg.xml) you might have a new session with each new transaction. If that is the case the you do not need to worry about putting too much stuff in there. You can find more info on contextual sessions here.
Since you have mentioned new transaction , then you would probably working with a new hibernate session belonging to thread ,
Use this incase of direct interaction with hibernate session
obj = session.merge(obj);
In case your using JPA2 Api
obj= entityManager.merge(obj);
Please rate the answer if it helps.
Cheers

stop doctrine from fetching related entities

When usually fetching an entity from database with doctrine, you get all the related entities as actual classes, which causes a huge JOIN query, if you have lots of relations.
But sometimes I just want to get the actual object, not all the associated entities, just their IDs.
Is it possible to tell doctrine to just fetch the main entity and leave alone the relations?
Update: Sorry, missed the version: I'm using Doctrine 1.2 on a old project.
By default Doctrine use "lazy-loading": it will not retrieve the associated entities if you do not try to access them.
If you just use the ID of the main entity, it will never retrieves the associated entities.
If you want it to be even more lazy, try using the EXTRA_LAZY param.

doctrine query in model or controller?

I'm using Codeigniter and Doctrine together for a project. I've gotten everything set up with both of these tools. But I'm not sure where I should have this bit of code:
$query = $em->createQuery('SELECT u FROM sessions u');
$sessions = $query->getResult(); // array of User objects
Should I be putting this in the controller or in the models/entities? At first thought, I figured I should put this kind of logic in the Sessions model, but it requires the entities manager $em, which I had thought should have been in the controller.
Thanks, this has been driving me crazy for the past half hour.
A lot of people like to create objects called DAOs or Data Access Objects to store this type of information.
The DAO contains the entity manager and methods that can be called and return the data you need. For example this function would reside in a DAO:
function findEmployeeById($emp_id)
And it would contain the query used to retrieve an employee from the database. In your controller you would just use the DAO instead of having an entity manager and dealing with it at that level.
But it really depends on preference and how large your project is.

how can i update an object/entity that is not completely filled out?

I have an entity with several fields, but on one view i want to only edit one of the fields. for example... I have a user entity, user has, id, name, address, username, pwd, and so on. on one of the views i want to be able to change the pwd(and only the pwd). so the view only knows of the id and sends the pwd. I want to update my entity without loading the rest of the fields(there are many many more) and changing the one pwd field and then saving them ALL back to the database. has anyone tried this. or know where i can look. all help is greatly appreciated.
Thx in advance.
PS
i should have given more detail. im using hibernate, roo is creating my entities. I agree that each view should have its own entity, problem is, im only building controllers, everything was done before. we were finders from the service layer, but we wanted to use some other finders, they seemed to not be accessible through the service layer, the decision was made to blow away the service layer and just interact with the entities directly (through the finders), the UserService.update(user) is no longer an option. i have recently found a User.persist() and a User.merge(), does the merge update all the fields on the object or only the ones that are not null, or if i want one to now be null how would it know the difference?
Which technologies except Spring are you using?
First of all have separate DTOs for every view, stripped only to what's needed. One DTO for id+password, another for address data, etc. Remember that DTOs can inherit from each other, so you can avoid duplication. And never pass business/ORM entities directly to view. It is too risky, leaks in some frameworks might allow users to modify fields which you haven't intended.
After the DTO comes back from the view (most web frameworks work like this) simply load the whole entity and fill only the fields that are present in the DTO.
But it seems like it's the persistence that is troubling you. Assuming you are using Hibernate, you can take advantage of dynamic-update setting:
dynamic-update (optional - defaults to false): specifies that UPDATE SQL should be generated at runtime and can contain only those columns whose values have changed.
In this case you are still loading the whole entity into memory, but Hibernate will generate as small UPDATE as possible, including only modified (dirty) fields.
Another approach is to have separate entities for each use-case/view. So you'll have an entity with only id and password, entity with only address data, etc. All of them are mapped to the same table, but to different subset of columns. This easily becomes a mess and should be treated as a last resort.
See the hibernate reference here
For persist()
persist() makes a transient instance persistent. However, it does not guarantee that the
identifier value will be assigned to the persistent instance immediately, the assignment
might happen at flush time. persist() also guarantees that it will not execute an INSERT
statement if it is called outside of transaction boundaries. This is useful in long-running
conversations with an extended Session/persistence context.
For merge
if there is a persistent instance with the same identifier currently associated with the session, copy the state of the given object onto the persistent instance
if there is no persistent instance currently associated with the session, try to load it from the database, or create a new persistent instance
the persistent instance is returned
the given instance does not become associated with the session, it remains detached
persist() and merge() has nothing to do with the fact that the columns are modified or not .Use dynamic-update as #Tomasz Nurkiewicz has suggested for saving only the modified columns .Use dynamic-insert for inserting not null columns .
Some JPA providers such as EclipseLink support fetch groups. So you can load a partial instance and update it.
See,
http://wiki.eclipse.org/EclipseLink/Examples/JPA/AttributeGroup

Resources