How to PUT just GETted entity with OneToMany relation back - spring-data-rest

For example I have those entities (slightly modified entities from restbucks example):
class Order {
// ID, getters etc
#OneToMany(mappedBy = "order", cascade = CascadeType.ALL, orphanRemoval = true)
Set<Item> items;
}
class Item {
// ID, getters etc
#ManyToOne
Order order;
}
And Repository for each.
Now if I GET /orders/1 then have a JSON with simple fields of order and link to the items of that order in _links attribute.
If I then modify some fields and just PUT that JSON back to /orders/1 then all fields modified correctly but in addition Set<Item> items is cleared. Actually they deleted as orphanRemoval = true. In hibernate logs I see:
Hibernate: select order0_.id as id1_3_0_, order0_.location as location2_3_0_, order0_.ordered_date as ordered_3_3_0_, order0_.status as status4_3_0_ from rborder order0_ where order0_.id=?
Hibernate: select items0_.order_id as order_id8_3_0_, items0_.id as id1_1_0_, items0_.id as id1_1_1_, items0_.milk as milk2_1_1_, items0_.name as name3_1_1_, items0_.order_id as order_id8_1_1_, items0_.currency as currency4_1_1_, items0_.value as value5_1_1_, items0_.quantity as quantity6_1_1_, items0_.size as size7_1_1_ from item items0_ where items0_.order_id=?
Hibernate: update rborder set location=?, ordered_date=?, status=? where id=?
Hibernate: delete from item where id=
But what if I need preserve that items? I must use PATCH? What if I want not to track from client which fields changes.
For example:
GET order from JS and assign it to variable
Do some changes to fields. Not track which fields changed.
PUT changed order back to the server.
Now the order has no items.

What you're trying to do is the intended purpose of PATCH.
Several applications extending the Hypertext Transfer Protocol (HTTP)
require a feature to do partial resource modification. The existing
HTTP PUT method only allows a complete replacement of a document. This
proposal adds a new HTTP method, PATCH, to modify an existing HTTP
resource.
https://www.rfc-editor.org/rfc/rfc5789

Related

How to change or remove target of object relationship in spring data neo4j?

In spring data neo4j I have simple one-to-many relationship: (:User)-[:EMPLOYEE_OF]->(:Company). User can be employee of only one company. Here are my entities:
class User(#Relationship(type = "EMPLOYEE_OF") var company: Company? = null, /* ids etc */)
class Company(/* ids etc */)
When I want to change target of that relationship or remove it neo4j keeps adding new relationships instead of replacing it.
val user = userRepository.findByName("user1")
val company = companyRepository.findByName("company1")
user.company = company
userRepository.save(user)
// 2nd case
user.company = null
userRepository.save(user)
In both cases, relationships are only added, never removed.
Is there a proper way to do it?
You have to put the load / find and the save in a transaction. The best way in a Spring project to do this is to extract the logic into a service layer method of your application and mark it as #Transactional.
Within this transaction, Spring Data Neo4j / Neo4j-OGM can track the changes that happen on the node and change or remove the relationships.

Sitefinity - Safely delete orphaned dynamic content records

I've been adding records to a dynamic module via the API and in the process during my experimentation I added a bunch of records that weren't associated correctly with any valid parent record.
I've checked and so far I can see that Sitefinity stores data about these records in a number of tables:
mydynamiccontenttype_table
sf_dynamic_content
sf_dynmc_cntnt_sf_lnguage_data
sf_dynmc_cntent_sf_permissions
I would like to clean up the database by deleting these records but I want to make sure I don't create more problems in the process.
Anyone know if there are more references to these dynamic content type records or a process to safely delete them?
There are probably other tables, so your safest option would be to delete the items using the Sitefinity API.
Just get the masterId of the item and use a code like this:
public static void DeleteDataItemOfType(this DynamicModuleManager manager, string type, Guid Id)
{
Type resolvedType = TypeResolutionService.ResolveType(type);
using (var region = new ElevatedModeRegion(manager))
{
manager.DeleteDataItem(resolvedType, Id);
manager.SaveChanges();
}
}

Hibernate: HQL delete from embedded map

I want to delete entries from an embedded map. If the object CategoryTag is deleted, I want to execute a HQL query in an interceptor, which deletes the entries from a map:
'Product' model:
#NotNull
#ElementCollection
#CollectionTable(name = "producttag", joinColumns=#JoinColumn(name="id"))
protected Map<CategoryTag, String> tags = new HashMap<CategoryTag, String>();
I am kinda blank how i can write the HQL query. It starts with the problem, that I do not know how to reference the map in a delete query. delete Product.tags t where t.key = :tag fails with an Product.tags is not mapped exception.
Can somebody help me on this?
Tags is not entity.
A delete operation only applies to entities of the specified class and its subclasses. It does not cascade to related entities.
This is why you are getting the error. The correct way is to load Entity, update its collection and then save this object.
Product p = session.load(Product.class, id);
p.removeTags(tag);
session.flush();

How to display only specific columns of a table in entity framework?

how to display the some specific columns of table instead of whole table in entity framework.
using (DataEntities cxt = new DataEntities())
{
notes note = cxt.notes.Where(no => no.id == accID).SingleOrDefault();
return notes;
}
For this purpose, I would suggest you to make use of ViewModel like following :-
notes note = cxt.notes.SingleOrDefault(no => no.id == accID);
var model = new YourViewModel // Your viewModel class
{
ID = note.ID,
PropertyOne = note.PropertyOne, // your ViewModel Property
PropertyTwo = note.PropertyTwo
};
You can do this with QueryView.
This implies editing your model directly in XML as there is no designer support for this, but you will get an independant entity with less fields than the original one.
Advantages:
You can then query data base for this truncated entity directly (you will get only fields you need from the data base - no need to get whole entity from DB and trancate it in code)
It is good in scenarios where you want to send this truncated entity to the
client
with WCF to minimize traffic (e.g. when building big lists on client
that basically need only name and ID and no other entity specific
information).
Disadvantages:
This QueryView-based entity is read only. To make it writeable you will have to add r/w functionality yourself

Using nhibernate ,to delete entity with details cascade-delete-orphan,why do I have to get the entity with all details, in order to delete them too?

Let's say I have the following entities:
public class Order
{
public int OrderID {get;set;};
public int Version {get;set;};
public IList<OrderDetail> Details {get;set;}
}
public class OrderDetail
{
public int OrderDetailID {get;set;}
/// Some other properties
}
When I want to delete the entity like this:
Order order = new Order { OrderID = 9, Version =1 };
ITransaction tr = Session.BeginTransaction();
Session.Delete(order);
tr.Commit();
Well the order is deleted, but the details is still there with (OrderID) foreign key set to null,
but when I try to delete it like this, it worked as expected:
Order order = Session.Get<Order>(9);
ITransaction tr = Session.BeginTransaction();
Session.Delete(order);
tr.Commit();
Why should I have to get the entire entity from database, in order to delete it?
BTW: I tried to create an instance of Order and fill the information and details information manually, it also worked
Can't I just do it as simple as possible ?
First, you are going against the principles of NHibernate with this approach. See Ayende's (he's one of the main developers behind it) response to this question in this thread)
If you are using NHibernate versioning (it looks like you are because of the presence of that Version property) then you will have to get the Order item from the database anyway because it shouldn't let you delete without the correct version number being provided and how would you know it without checking the database?
The idea below may work:
Create the reference to the Order entity the "NHibernate" way. The Correct way to reference a persisted entity without making a call to the database is to use the Session.Load function. This will return a proxy object of the entity in question which can hydrate itself from the database if needed. You would need to replace this line:
Order order = new Order { OrderID = 9, Version =1 };
with
Order order = Session.Load<Order>(9);
You will have to check with a profiler or logger to see if the Order was actually rehydrated from the database in this instance (which to be honest I think it will).