I'm working on an application that manages two tables in a database with JPA. The first one contains Users and the second one Items; one user can have many items but an item only corresponds to one user. This means that theres is a One to Many relation from Users to Items and a Many to One relation from Items to Users.
My application is a RESTful service and I am currently transferring DTO's over the web to a web application where the entities information are displayed. When I convert information from a User entity to a User DTO, I cant send all its items, since they can be too many, so I take an entity from the Users database and convert it into a DTO with no Items.
My question is, if I want to update a User's information, when I convert the DTO back to an entity it will not have any Items, so, how can I save the changes conserving the foreign keys that represent the User items before updating its information?
I know that the EntityManager uses a merge() method to update information in the database, but, wouldn't this affect the foreign keys I want to preserve? since I'm trying to save an Entity with no Items?
You need simply retrieve a user object from EM,
update the fields that has changed (or all)
commit transaction (if you manage the transaction mannualy)
DTO modification = ...
em.getTransaction().begin(); //if it is not container managed
User user = em.find(User.class,modification.getId());
user.setName(modification.getName());
user.setXXX...
em.getTransaction().commit()l //if it is not managed
Typically, the items will be lazy loading, so they will not be retrieved at all. Even if, the User object retrived from the JPA will have the full info about them, as long as you are not modifying its itmes content, the items will remain intact.
Related
We're currently developing a .Net Core console application which consumes a web service to fetch data and inserts it to a database asynchronously.
Web service returns an object - to make the problem simple let's call it Orders - has a Country, Date and Ordered By fields. In our database we have a Countries and Orders table with 1 to Many relationship.
When the app starts it stores the country list in a static List property. As a new Order from web service is returned, country field is checked if exist in the current List property to get Id field from it. If it doesn't exist, a new record is inserted to the database and List property is updated with a helper method. This scenario works without any problem in single thread. However when we make the web service requests and update the database asyncronously, each async Task updates List property independently and that causes multiple country values with the same name.
Is there a best practice to keep country list updated only when a new record is inserted and prevent inserting the same values by different Tasks?
Kind regards
Is there a best practice to keep country list updated only when a new record is inserted and prevent inserting the same values by different Tasks?
Yes. Put a unique index on the Country entity's Name property. Then when you attempt to add a duplicate Country, it will fail and you can retrieve the ID of the existing country instead.
Let's say I have a Book Entity with a ManyToOne relation to Author entity.
On a page listing all the books, I have a search Form with a field 'Author'.
I store the data of my search form in an object (not en entity, not persisted) called searchFilter.
I made a SearchFilterType in which I'm using the EntityType class in order to display a choice list of the authors, so one can search all the books with this author.
When I visit another page and then come back to the search page, I want my last search to be remembered, that's why I'm storing the searchFilter object in the session.
$request->getSession()->set('searchFilter', $searchFilter);
But when I go back to the search page, I get the error:
Entities passed to the choice field must be managed. Maybe persist them in the entity manager?
My question:
Do I have to turn my searchFilter object into an entity in order to persist it, or is there an easier way? I don't want my searchFilter to persist forever, session time would be enough.
EDIT:
I think my question is a duplicate of this one where excellent solutions were offered.
Sessions cannot store objects. Therefore you need to serialize and de-serialize your object. see http://symfony.com/doc/current/components/serializer.html
And see this simple implementation example
I have two domain classes with a many-2-many relationship between them, e.g. User and Group. There's a user2group table in the database to map this relationship. If I want to set User's Groups based on a list of Group IDs (which might come e.g. from a HTML form) do I really have to fetch the Groups first to update the User through setUsers(Set<Users>)? I already have the Group IDs and they are actually the only information needed to update the mapping table...
I'm using Spring Data JPA and Hibernate as the provider.
You can write a native query, but the whole point of ORM is to use it. You may not have to fetch the Group if the owning side of the relationship is on the User, but it's most common to define it on the Group. In this case, if you are going to use the ORM, yes, you have to fetch the Groups.
I have two entities, User and UserSetting. The obvious relationship between these two has User as the first rate entity which contains a set / list of UserSettings so when a User is loaded the settings get loaded too. E.g User 1-->* UserSetting
Trouble is that's not what I want. At the moment users only have a few settings but that won't always be the case and when a user is active in the system they typically only need access to a small subset of all their settings. What I want is to load individual user settings on demand. The obvious choice is to make the UserSetting list lazy load but that won't work as I want to use the User in a detached state.
My current "solution" is to include the User in the UserSetting object but that feels wrong as it makes the relationship UserSetting *-->1 User which feels like the UserSetting is the dominant entity. Is this the best solution?
Assuming my current solution is the best I can get will a delete of the User still cascade correctly?
There's 2 points here
First, if your User entity has an association towards UserSettings and that association can contain a lot of members which are not needed all the time, the right thing to do is configure it as lazyLoaded by default (via JPA2 mapping config) and then force an eager fetch on it only when you need to (i.e. in those situations you mentioned where you need the values of that assocation on a detached User Entity). Look at "join fetch" to see how to do this, it should be something like:
SELECT u FROM User u JOIN FETCH u.userSettings
If there's only a subset of those UserSettings that are needed often, you could make two associations in the User entity, such as userSettingsMain and userSettingsExtra, both lazy loaded by default, and just join fetch the one you needed on a certain detached User entity. Or, as a more advanced thing, you can make a Map association on the user settings, and have different keys for the important UserSetting, and the extra ones (such as i1, i2,... e1, e2, etc) and then eagerly fetch only those sets of keys that are needed, but this only works (at least at the moment) with EclipseLink JPA2, Hibernate's implementation just throws a big exception on Map associations (see my question here: Hibernate JPQL - querying for KEY() in Map association error on this)
In my ASP.net MVC application, i want to store the information, that was edited or created, in several different entities (persons, address, ..).
So my create view exist of input fields for each attributes in persons table and address table. Now I want to store the values in both entities at the same time?
Is this the same approach as with retrieving using a ViewModel? Or is there a better approach ?
You could indeed make your view typed to a view model that encapsulates all the entties you need for that view, but when it's time to store them in the database you'll still have to do it every entity individually, so for example you have:
// here you got hold of your entities already;
// we are in your action method
// this is your context, but please use
// Dependency Injection in your controller ^_^
var context = new dbContext();
context.Add(person);
context.Add(address);
// This will store all the entities you've added in one go.
context.SaveChanges();
SaveChanges() works as well when you neet do update entities, as long as you retrieve said entities through the same context.