How to retrieve an Entity Object just with #Id (Proxy object), check if it exists and assign it to a #ManyToOne association - spring-boot

I have an entity Product which have many fields and associations (around 60).
And a table ProductView which has a #ManyToOne(fetch = FetchType.LAZY) association with Product.
Is there a optimal way to retrieve Product object and assign it to ProductView ?
If its used JPA findById(productId) or JPQL/EntityManager selects-> It will retrieve all products fields and associations
Product product = productRepository.findById(productId);
ProductView productView = new ProductView(product);
save(productView);
If its used JPA getOne -> It solves the problem but the Proxy can throw error if Product does not exists. And this error can not be handled because it happens at runtime.
Product product = productRepository.getOne(productId);
ProductView productView = new ProductView(product);
save(productView);
If a DTO is used or Interface which refers to the same Product Table -> We will get just an object with Id field, but a lot more processes will need to be added (Which I am not familiar with)
Delete foreign keys from ProductView table (#ManyToOne -> #Column) and simple assign productIds. But in this way, there will be no logic connection between tables.
ProductView DB
How usually developers avoid this problem ?

I don't understand what the problem is. Just use getOne approach and at the end of your method, use flush which will throw the constraint violation exception that you can handle. This is the way to go.

Related

Check ManyToOne eager and lazy relations for null

Suppose that a certain booking's invoice is null in the DB.
public class Booking {
#Id
private Integer id;
...
#ManyToOne(... fetch = FetchType.LAZY)
#JoinColumn(...)
private Invoice invoice;
}
It seems that a many-to-one lazy relation always creates a proxy object for booking.getInvoice(), while an eager relation would just return a null. I think I can check the booking.getInvoice().getId(), but for that I must be sure that the relation is lazy. I don't want to do that because it forces me to always track the relation fetch type in the client code.
What if I have a lot of existing code that checks null in 'eager mode' and I want to convert a certain relation to lazy? Do I have to convert all null checks for that relation as well?
I'd think that since the DB field is null then the JPA would be smart enough to not create the proxy object at all here, leaving the private field invoice null.
Is the double check for null and id the only way to go?
Invoice invoice = booking.getInvoice();
if (invoice != null && invoice.getId() > 0) {
...
}
Is there a fetch-type-independent way to check for null many-to-one children in JPA?

Create a relationship by ID using Neo4J and Spring Data

I have defined a simple node object like this:
#Node("product")
public class Product {
#Id
private String sku;
...
#Relationship(type = "SOLD_BY")
private Set<Shop> shops = new HashSet<>();
...
}
However, my concerns are:
To create (and save) a new Product I must not only create the Product, but also the list of Shop objects. And maybe a Shop object holds an Address object or a list of Employees itself. This means I'm forced to construct a huge list of objects.
Also, maybe the Shop objects are already existing in the database and I don't want to overwrite them by saving the new Product.
By loading a Product, all related Shop objects will be loaded and so on. But I'm just interested in the Product, not in everything connected to it.
So instead I want to do this:
#Relationship(type = "SOLD_BY")
private Set<String> shops = new HashSet<>(); // Just the IDs of the Shops
Is this possible?
Is this a valid approach to solve my problem?

Error on JPA many-to-many relationship between entity table and join table

I want a many-to-many relationship between an entity table and a join table. Invoices consist of a set of subscriptions. A subscription can be a part of multiple invoices (e.g. monthly subscription). Subscriptions consist of a user and a service. I am already using the subscriptions table as a join table for the many-to-many relationship between users and services (e.g. a user can subscribe to multiple services and a single service has multiple users). I have a table, "invoice_subscription," with IDs for both the invoice and subscription. Every table has its own ID. Below is the relevant snippet in the invoice object:
#ManyToMany
#JoinTable(
name = "invoice_subscription",
joinColumns = #JoinColumn(name = "invoice_id"),
inverseJoinColumns = #JoinColumn(name = "subscription_id")
)
public Set<Subscription> getSubscriptions() {
return subscriptions;
}
I am using the following in the subscription object:
#ManyToMany(mappedBy = "subscriptions")
public Set<Invoice> getInvoices() {
return invoices;
}
For the above, I am receiving the error below:
org.hibernate.MappingException: Foreign key (FKfe5yu82iapjynsdyfitclkri4:invoice_subscription [subscription_id])) must have same number of columns as the referenced primary key (subscription [user_id,service_id])
When I switch to two "#JoinColumn" annotations with the IDs in the error, I get the following error:
org.hibernate.AnnotationException: A Foreign key refering com.example.model.Subscription from com.example.model.Invoice has the wrong number of column. should be 1
I agree with this, but it seems to contradict the previous error. I've read documentation, guides, and other questions, but I have not found any useful information. I'm clearly missing something obvious.

Saving complex view model using Entity Framework 4.3

I have Customer, Order and OrderItem tables. OrderItem.OrderID points to Order.ID; and Order.CustomerID points to Customer.ID i.e. the common Customer -> Order -> OrderItem setup.
And I have a view model – Customer which contains Order objects and then OrderItem objects as well.
If the user creates a new Customer, new Order and new OrderItems on a view, which are then bound to the Customer view model object (containing all Customer, Order, OrderItem data); is there a way to save this Customer view model using EF?
My confusion comes from the fact that, since Customer, Order, OrderItem(s) are all new records; which means the Customer.ID (auto-incremented number) has not been generated yet (record not saved yet); so how does EF know what ID to use when saving Order.CustomerID?
Do I need to save Cusomer first, get the Customer.ID, then save Order, then get Order.ID and then save OrderItem(s)?
Thanks.
You just call this:
context.Customers.Add(customer);
context.SaveChanges();
and if everything is correctly configured in your mapping EF will understand relations and correctly save customer first, retrieve its Id and use it for saving related orders. It will handle order items in the same way.
As long as you establish the objects relationships before saving it should work
customer.Orders = new List<Orders>();
customer.Orders.Add(order);
order.OrderItems = new List<OrderItems>();
order.OrderItems.Add(orderItem);
context.Customer.Add(customer);
context.SaveChanges();

Spring-Hibernate: How to submit a for when the object has one-to-many relations?

I have a form changeed the properties of my object CUSTOMER. Each customer has related ORDERS. The ORDER's table has a column customer_id which is used for the mapping. All works so far, I can read customers without any problem.
When I now e.g. change the name of the CUSTOMER in the form (which does NOT show the orders), after saving the name is updated, but all relations in the ORDERS table are set to NULL (the customer_id for the items is set to NULL.
How can I keep the relationship working?
THX
UPDATE: Mapping Info
The Orders are mapped on the Customer side
#OneToMany
#JoinColumn(name = "customer_id")
#OrderBy("orderDate")
private Collection<Order> orders = new LinkedList<Order>();
UPDATE
Seems like adding a
#SessionAttributes("customer")
to my model, changing the method to
public String saveTrip(#ModelAttribute("customer") Customer customer, BindingResult result, SessionStatus status) {
if (!result.hasErrors()) {
this.tripManager.saveTrip(trip);
}
else {
logger.debug("Form data included errors, did not save data");
BindingUtils.logBindingErrors(result, logger);
}
status.setComplete();
return "redirect:/customers/";
}
Could solve the issu. But is this a good way of solving it???
One way would be not to submit the CUSTOMER Object from the form.
Instead submit the customer, submit only the customers ID and the new Name. In the controller you have to load the Customer by the submitted ID and then update the Name. And persist the Customer again.
HI,
Make cascade="none" attribute of many-to-one relationship from order side.
Thanks.

Resources