Why should we use #Enumerated in JPA? - spring

I have an enum named difficulty and I marked it with #Entity and it has a one to one relationship with the recipe class. I ran my program in spring boot and it ran without any problem. My question is, why do we have to use #Enumerated? What's wrong with the way I went?
Enum:
#Entity
public enum Difficulty {
EASY,MODERATE,HARD;
#OneToOne
private Recipe recipe;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
public Long getId() {
return id;
}
}
Recipe class:
#Entity
public class Recipe {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#OneToOne
private Difficulty difficulty;
}
with #Enumareted:
#Entity
public class Recipe {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#OneToOne
#Enumerated(value=EnumType.STRING)
private Difficulty difficulty;
}
If we go with #Enumrated, we have to remove #Entity from Difficulty(I wrote Recipe which corrected), which I didn't write.

Enum are not associations (although you can create a colletion of enums with #ElementCollection, but it's a different scenario), so you don't need the #OneToOne if you use #Enumerated. The mapping should be:
#Entity
public class Recipe {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Enumerated(STRING)
private Difficulty difficulty;
}
enum Difficulty {EASY,MODERATE, HARD;}
The value will be stored as a column in the table representing Recipe.
A one-to-one association means that every time you save a recipe, you are also creating a new Difficulty. You are using enums, so I don't think that's what you want (are you sure your mapping actually works?).
Without using enums, a mapping that would make sense, would be:
#Entity
public class Recipe {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#ManyToOne
private Difficulty difficulty;
}
#Entity
public class Difficulty {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long difficultyId;
private String level;
}
or, if you want to use enum and associations:
#Entity
public class Difficulty {
enum Level {EASY, MEDIUM, HARD;}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long difficultyId;
#Enumerated(STRING)
private Level level;
}
Having a different entity means that the difficulties are stored as rows in a separate table Difficulty. Because it's a many-to-one association, you can associate different recipes to the same difficulty.
It also means that Hibernate will need a join or a separate query to load the difficulty. I don't see the benefit if you are only interested in the name of the difficulty.
Ultimately, it depends on your use case and how you want the data to appear in the database.
But if you can use enum and there is only one level per recipe, mapping it as a column seems a simpler solution.

Related

How to create entity with self-referencing (with many To many mapping)

#Entity
public class Department {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
#ManyToMany(mappedBy = "departements")
private List<Department> departements;
I don't know how to implement this association .In my situation I have the same entity mapped by itself by many to many

Troubles with Bidirectional One-To-One JPA

I'm coding a CRUD JPA web application. My goal is that a given parent Vehicle can only have a single child Driver, but during runtime this same Driver can instead be assigned to another Vehicle and vice versa. To my understanding, this could be accomplished via an OneToOne relationship.
I've tried some different approaches, but to no success. I can assign a Vehicle to a Driver just fine, but when I try to update/create a new Vehicle and give him a Driver, via controllers, nothing happens. I can only do it the other way around. I'm assuming this is because Vehicle is the parent and I can only create a new relation by updating a parent.
My question is, is it possible to make these updates bidirectional and how can I achieve that?
I've tried using a shared primary key, using a foreign key, using a join table. The result is always the same and I can't quite grasp why. I have an OneToMany relationship working on this application and it works as I expect it to work. I can update on one side or the other, delete on one side or the other. Both entities have been updated. OneToOne? Parent seems to have all the power.
This is what I'm working with right now:
Driver
#Entity
#Table(name= "drivers")
public class Driver {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column(nullable = false)
private String name;
#Column(nullable = false)
private int age;
#OneToOne(mappedBy = "driver")
private Vehicle vehicle;
Vehicle
#Entity
#Table(name= "vehicles")
public class Vehicle {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column(nullable = false)
private String make;
#Column(nullable = false)
private String model;
#Column(nullable = false)
private int mileage;
#Column(nullable = false)
private int year;
#Column(nullable = false)
private int fuel;
#OneToOne
#JoinColumn(name = "driver_id")
private Driver driver;
And just for reference, this is the OneToMany relationship I have and that I'm happy with. I'd like my OneToOne to have the same behavior, except I don't need to save a list of entities, only one.
#Entity
#Table(name="stops")
public class Stop {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column(nullable = false)
private String name;
#ManyToOne
#JoinColumn(name="route_id")
private Route route;
#Entity
#Table(name="routes")
public class Route {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column(nullable = false)
private String name;
#OneToMany
#JoinColumn(name = "route_id")
private List<Stop> stops = new ArrayList<>();
Any tips would be appreciated, thank you for your time.

Spring JPA - Get all Child Elements

I have the following POJOs'
Filter ----> Filter Components
#Entity
public class Filter {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String name;
//Setters and getters are not shown
And I have the following child class
#Entity
public class FilterComponents {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private int component_id;
private int component_type;
#ManyToOne
#JoinColumn(name = "filter_id")
private Filter filter;
//Setters and getters are not shown
I created a repository to query for Filters
public interface FilterRepository extends JpaRepository <Filter, Long> {}
I am calling the findAll() function to get all Filters. The function is working fine; however, it only returns the name and id of each filter.
Is there a way to return the corresponding Filter Components as well? I assume I can write a join query, but I have a feeling that there is a cleaner way to do it!
Thank you
Make Filter to FilterComponents a OneToMany unidirectional mapping. So, you will be managing child FilterComponents inside its parent.
#Entity
public class Filter {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String name;
#OneToMany
#JoinColumn(name = "filter_id")
private List<FilterComponents> filterComponenets;
}
#Entity
public class FilterComponents {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private int component_id;
private int component_type;
// Removed mapping
}
What you probably missing is a filterComponents field for a Filter e.g.
public class Filter {
...
#OneToMany(mappedBy="cart")
private List< FilterComponents> filterComponents;
You can define eager or lazy fetching depending on your needs here
Your Filter entity does not have any explicit association with FilterComponent entity. In this case you would need to do another request to select all filter components with the given filter id.
On the other hand you can declare the following field in the Filter entity:
#OneToMany(mappedBy = "filter", fetch = FetchType.EAGER)
private List<FilterComponent> filterComponents;
and always load filter components eagerly.
If eager loading does not fit you you can use custom query with left join fetch:
select distinct f from Filter f left join fetch f.filterComponents c

Spring Boot one to many unidirectional

I have the entity Project and entity Cluster.
A Project can have multiple Clusters.
I don't want a third table to save this relationship. Just the Project ID saved to the Cluster.
This is my project Entity:
#Entity
#Table(name = "Project")
public class Project {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
private String projectName;
#OneToMany
#JoinTable(name = "cluster")
private Set<Cluster> clusters;
}
This is my Cluster entity
#Entity
#Table(name = "Cluster")
public class Cluster {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
private String team;
private String concept;
}
This gives me the error: must have same number of columns as the referenced primary key .
How could I fix this? I don't see how to fix this.
Use #JoinColumn instead of #JoinTable
public class Project {
//...
#OneToMany
#JoinColumn(name="PROJECT_ID", referencedColumnName="id")
private Set<Cluster> clusters;
and add PROJECT_ID column to Cluster entity.
public class Cluster {
//...
#Column(name = "PROJECT_ID")
private Integer projectId;
Correct me if I'm wrong but, as far as I know about Software Engineering, what you want CAN'T be done: you can't store a relationship nowhere but in a third table. Lists, sets, maps, and so on MUST be stored that way.
Otherwise, and in your case, you'd have Project's properties replicated for each cluster of the relationship, and that's not desirable.

Spring JPA not in

I have two class Drug and medicalDrawer.
I search a way to get all medicalDrawer not used in Drug
#Entity
public class Drug {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long drugId;
#OneToOne
private MedicalDrawer medicalDrawer;
}
#Entity
public class MedicalDrawer {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long medicalDrawerId;
private String name;
}
If you are using Spring and JPARepository, it supports quite a lot keywords like : 'And', 'IsNull', similarly 'NotIn'.
Check this out: http://docs.spring.io/spring-data/jpa/docs/current/reference/html/
Now, coming to your question, here is my approach:
Get all the drugs using findAll(), loop through and add medicalDrawerId in a list say medicalDrawerDrugList.
Find MedicalDrawer, which are not in drugs. For that, you can
write something like this:
findByMedicalDrawerIdNotIn(medicalDrawerDrugList);
I hope, this helped.

Resources