How to link an entity with database? - session

I have a complex entity with many relations, so I need many forms in many pages to create one. Therefore, I use a session to keep my entity.
Everything is going okay, but when comes the time to flush, the entity manager returns the "entity through relationship is not configured to cascade persist" thinking that some entities are new but they're actually stored in db !
For instance, I create a User with a ManyToOne Group, using $u->setGroup(Group $group); ($group being an existing group from the db). When I put it in session, then get it back in another page and then flush it, the entity manager tries to create a whole new group, not knowing that it is an existing one in db.
I use a little trick to overcome this :
$u = $this->get('session')->get('userToAdd');
$group = $em->getRepository('MyBundle\Entity\Group')->find($u->getGroup()->getId());
$u->setGroup($group);
With this, EM will recognize the group stored in db and the flush will go just fine, but with my entity having so much relationships like this, it is very convenient to do this for every single one.
Any ideas for this issue ?

Before find group try to refresh $u object.
$em->refresh($u)

You have to do:
$em->merge($u);

Related

Panache: Insert or ignore child

I want to persist an entity that has a #OneToMany relationship to a child entity. I'm using Quarkus 1.13.1 with Quarkus Panache.
Example
public class User {
private List<Item> items;
#OneToMany(cascade = CascadeType.ALL)
public List<Item> getItems()...
}
If I want to persist a user (user.persist()) with a few items that already exist in the item table, then I get of course a "duplicate key" exception. So far so good.
But I was wondering if there is a descent way to skip/ignore an insert if an item already exists in the table items.
Of course, I could query the database to check if the child value exists, but this seems somehow tedious and bloats the code with data checks, so I was wondering if there was some annotation or other shortcut to handle this.
A persist operation should be used exclusively to create (store) new objects in the database, and makes the Java objects managed by Hibernate until the Session is closed.
It's really important that you know which objects are managed, and which are not, and distinguish wich ones are newly made persistent rather than just represent an existing object in the database.
To this end, it would indeed be better to load the existing Items first; if you know for sure which ones are already existing in the DB you can use a lazy proxy to represent them and put those in the list before persisting the User.
If you don't know which Items already exist in the database, then you should indeed have to query the database first. There is no shortcut for this operation; I guess we could explore some improvements but generally automating such things is tricky.
I would suggest implement the checks explicitly so you have full control over the strategy. It might be a good idea to make Item a cached entity so you can implement safe validations without performance drawbacks.

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

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

MSCRM: How to create entities and set relations using the xRM linq provider

Do I need to save newly created CRM-entity instances before I can set relations to other crm entity instances?
I'm facing the problem that after calling CrmDataContext.SaveChanges() the newly created entities are written to the database, but the relations between those newly created instances are missing in the database.
What do I miss? Do I have to call CrmDataContext.SaveChanges() each time I create a new crm entity instance that I want to have relations to other CRM-entity instances?
You should be able to set relationships to other entities in a 1:N relationship before saving this entity(i.e. a lookup).
If you are wanting your entity to be referenced by another entity it will need to be Saved first OR you need to set a Guid for the entity first. Otherwise your link won't stick.
When you new up an entity its id is not set until it is saved to the database, unless you set it manually. If you set it manually it will respect the new Guid you have given it and the relationship will survive the saving process.
If you try to save an entity individually, you need to make sure that you have saved all the entities that it refers to before you save that entity, or it won't have a link.

Resources