Hibernate map nested object on columns of parent's object table - java

I have two objects in my model:
#Entity
#Table(name = "project")
#Getter
#Setter
public class Project extends BaseData{
...
private PaymentMethod paymentMethod;
...
}
.
#Getter
#Setter
public class PaymentMethod {
private Boolean requestRequired;
private Integer timeLimit;
}
What I want to do is to map requestRequred and timeLimit fields on columns of project table so there is no need to create one more table to store PaymentMethod objects in.
Is it possible in general and is it a common practice to do this? It seems a little bit counterintuitive for me and difficult to maintain. But on the other side a lot of tables lead to performance issues as far as I know.
Thanks for help!

Related

Java Spring Hibernate JPA PostgreSQL Avoid saving duplicate rows / records

I'm very green when it comes to databases. I feel like this is probably a pretty common database problem, I can't seem to find the correct search terms to find my answer.
My issue is "duplicate" rows in a table. I'm trying to save restaurant food menus in a database, and for the most part its working alright. I have a object called RestaurantWeek, which contains a list of RestaurantDay objects and each day contains a list of RestaurantCourse objects. They get saved as such in the database: image. "weeks_days" and "days_courses" tables are the link between the "weeks", "days" and "courses" tables.
Now the problem comes when many days can have the same "course". Almost every single day has "Salad" as a course, so what ends up happening is I have 12 identical rows in my "courses" table, the only exception being the id column: image. So now the question is, how can I tell JPA or Hibernate to use the existing "Salad" row in my "courses" table instead of inserting a new one every time? Is it possible to do this by adding some specific annotation to my objects or their properties?
I have tried setting the "name" property on "RestaurantCourse" to unique with #Column(unique=true) but then I get errors about hibernate trying to save multiple courses with the same name (since name must be unique). I have tried grabbing the "courses" table when saving data and using the same id multiple times, but then I get errors about hibernate trying to save multiple courses with the same id (since id must be unique).
Is it even possible to fix this "easily", such as with few specific annotation I'm in the unknown about? Do I need to change something else about how my data is saved to the database, such as the classes, the annotations, or the way I'm trying to save?
Here are my classes.
#AllArgsConstructor
#NoArgsConstructor
#Data
#Entity
#Table(name="weeks")
public class RestaurantWeek {
#Id
private long id;
private Date saveDate;
private String weekName;
#OneToMany(cascade = CascadeType.ALL)
private List<RestaurantDay> days;
}
#AllArgsConstructor
#NoArgsConstructor
#Data
#Entity
#Table(name="days")
public class RestaurantDay {
#Id
#GeneratedValue (strategy = GenerationType.IDENTITY)
private Long id;
private String day;
#OneToMany(cascade = CascadeType.ALL)
private List<RestaurantCourse> courses;
}
#AllArgsConstructor
#NoArgsConstructor
#Data
#TypeDef(name = "list-array", typeClass = ListArrayType.class)
#Entity
#Table(name = "courses")
public class RestaurantCourse {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#Column(unique = true)
private String name;
private String price;
private String type;
#Type(type = "list-array")
#Column(name = "tags", columnDefinition = "text[]")
private List<String> tags;
}
And what I'm using to save:
#Repository
public interface RestaurantMenuRepository extends JpaRepository<RestaurantWeek, Long> {
}
public class RestaurantMenuServiceImpl implements RestaurantMenuService {
#Autowired
private RestaurantMenuRepository restaurantMenuRepository;
#Override
public RestaurantWeek addNewWeek(RestaurantWeek restaurantWeek) {
return this.restaurantMenuRepository.save(restaurantWeek);
}
}
Thanks in advance.
Yes is posible, you must use existing entity. But use in this method
public RestaurantWeek addNewWeek(RestaurantWeek restaurantWeek) parameter RestaurantWeek is not correct try put this method some dto class with need field to create entity class, additionally pass the parameter to available identify courses entity find which you can doing relationship and add to days entity.
No pass all parameter every time!
Alright, finally found the correct search terms and found the answer. Resolution was a combination of serob's answer and a bunch of googling.
In RestaurantDay I changed #OneToMany to #ManyToMany.
I created repository interfaces for RestaurantDay and RestaurantCourse.
When saving the course, I save the courses first, then the days, and finally the week, while grabbing all the new ids.
public RestaurantWeek addNewWeek(RestaurantWeek restaurantWeek) {
for (RestaurantDay day : restaurantWeek.getDays()) {
for (RestaurantCourse course : day.getCourses()) {
RestaurantCourse dbCourse = this.restaurantCourseRepository.findCourseByName(course.getName());
if (dbCourse == null) {
course.setId(this.restaurantCourseRepository.save(course).getId());
}
else {
course.setId(dbCourse.getId());
}
}
this.restaurantDayRepository.save(day);
}
return this.restaurantMenuRepository.saveAndFlush(restaurantWeek);
}
Try #NaturalId, this would make your name an Id for the Course entity:
https://vladmihalcea.com/the-best-way-to-map-a-naturalid-business-key-with-jpa-and-hibernate/

Query DSL advance sorting with spring pageable

) I have some problem with sorting and spring pageable when I use QueryDSL. I need quite advanced sorting, not just by the fields of the object stored in the database in the same table.
This is my model in approx:
#Getter
#Setter
#Entity
public class Book {
#Id
#GeneratedValue
private long id;
#OneToMany
private Set<Category> cats = new HashSet<>()
}
#Getter
#Setter
#Entity
public class Category{
private long id;
private Name name;
}
public enum Name{
WINTER,
SUN,
SUMMER
}
Now, this what I want to do is sort (desc and asc) Book (I have many Books) by Category id only if Category has name SUN. And i want to pass Qsort as Sort interface to PageRequest sping class.
I have no idea how I can achieve it. I try many way but none of these are even close to resolve this problem (for example some subquery with invoke any() on collection and use Qsort class). I affraid I made a mistake using Query DSL rather than Criteria Api. Can someone direct me? I will be very grateful.
Best Regards

JPA (hibernate) mapping child objects by field

EDIT: For those who may pass through here in the future, I'd like to share something I found. Although it's not going to work for this particular situation, hibernate does have an #Where annotation. With this annotation you could have N amount of Sets. Each set would have #Where(clause='column=value'). I will not be using the #Where solution but it may work out for you.
I'm new(ish) to JPA Hibernate and am looking for some help. I don't necessarily know what to search for either so here is a quick example of my problem.
I need to take a Set and split it into multiple Set dependent on a value of a field.
Lets look at something simple:
public class Customer{
private String name;
private String age;
private Set<Order> orders;
}
public class Order{
private int amount;
private String status;
}
Goal: I would like to have Hibernate split my Customer's orders by their status into seperate Sets. Currently I use the #POSTLOAD annotation to loop over the Set and seperate them out accordinly. I would prefer Hibernate do it for me resulting in something like:
public class Customer{
//Irrelevant stuff from above...
private Set<Order> pendingOrders;
private Set<Order> completedOrders;
private Set<Order> canceledOrders;
}
These sets would be based off the order's status.
pendingOrders is where Order.getStatus() == "PENDING"
completedOrders is where Order.getStatus() == "COMPLETED"
canceledOrders is where Order.getStatus() == "CANCELED"
The tables are directly represented by the classes and are both considered "Entities". (Customer and Order)
If I haven't provided adequate information, could you please point me to a proper search for what I am "trying" to accomplish. In terms of JPA terminology I have no idea what to search for and could really use some help!
Thank you!
The best approach in your case is create a discriminator column and some extra classes to use it. Example
#Entity
#Table(name = "ORDER")
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(name = "STATUS", discriminatorType = DiscriminatorType.STRING)
public abstract class Order{
}
#Entity
#DiscriminatorValue(value = "PENDING")
public class PendingOrder extends Customer {
}
public class Customer{
//Irrelevant stuff from above...
private Set<PendingOrder> pendingOrders;
//same fo0r all others types
}
And if you notice the orders have some specific information only valid for pending orders or completed orders, then probably the best approach is use
#Inheritance(strategy = InheritanceType.JOINED)
Or
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
And add the specific columns in those new tables

How to update/save document that include referance using morphia for mongodb?

So i have the following class:
#Entity("Item")
#ToString(callSuper=true, includeFieldNames=true)
#EqualsAndHashCode
public class Item {
public Item() {
this.timestamp = UUID.randomUUID();
}
#Id
#Getter
#Setter
private ObjectId id;
#Getter
#Setter
private UUID timestamp;
#Getter
#Setter
#Reference (lazy=false)
private GeneralInfo generalInfo;
}
while trying to save/update the item into mongodb, i have to first save the generalInfo class first and only then i can save the item class. i get it that the tables are dependand now, but is there a way to let morphia/mongo know what i want to use "deep update / save" or something like that?
No. Morphia does not support cascading saves like that. The use of references is largely orthogonal to the recommended way to model your domain (we encourage/recommend embedding documents) so supporting such a feature doesn't make much sense.

Mapping 1 table to multiple classes in JPA

I want to achieve something like this:
#Entity
#Table(name = "beer")
public class Beer {
#Id Long id;
String brand;
String name;
}
#Entity
public class BeerWithIngredients extends Beer {
#OneToMany(mappedBy="beer")
List<BeerIngredient> ingredients;
}
#Entity
public class BeerIngredient {
#Id Long id;
// .. whatever fields
#ManyToOne
#JoinColumn(name = "beer_id")
BeerWithIngredient beer;
}
Physically, all beer data is in one table, but I want to split it into more entities.
Please note that:
I would not like to use discriminator column in the database
There isn't a column that I could use for #DiscriminatorFormula
I do not want to embed Beer inside BeerWithIngredients, because it essentially is not a composition, but proper inheritance
Is there a way of achieving this with JPA (Hibernate)? Right now it complains about missing discriminator column, that I don't plan to provide.
Introduce a new super class RootBeer with all common beer properties. Annotate this class with MappedSuperClass. Make Beer and BeerWithIngredients inherit from RootBeer and annotate them with Entity as well as Table(name="beer").
For an example check this.

Categories

Resources