Spring JPA not in - spring

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.

Related

Why should we use #Enumerated in JPA?

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.

Hibernate returning PersistentBag instead of List

I have following relationship b.w two entities given below ,when I get OutletProductVariety object from repository ,the price is coming in PersistentBag and not as a List even after using fetchtype Eager.
#Entity
public class OutletProductVariety {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
Long id;
#ManyToOne
#JoinColumn(name = "varietyId")
Variety variety;
#OneToMany(mappedBy = "outletVariety", fetch = FetchType.EAGER)
List<Price> price;
}
And
#Entity
public class Price {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
Long Id;
#ManyToOne
#JoinColumn(name="outletVareityId")
private OutletProductVariety outletVariety;
private Double price;
}
How can I get a List of prices rather then PersistentBag?
Have a look at Hibernates PersistentBag
An unordered, unkeyed collection that can contain the same element
multiple times. The Java collections API, curiously, has no
Bag. Most developers seem to use Lists to represent
bag semantics, so Hibernate follows this practice.
public class PersistentBag extends AbstractPersistentCollection implements List
protected List bag;
It implements java.util.List; so it is basically a List and wraps your List internally
It is just Hibernates way to represent your List.

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

Like Button Implementation in Spring Boot

In my application users can post articles. And other users can like these articles.
Article class :
#Entity
public class Article {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "article_id")
private int id;
#Column(name = "article_title")
private String articleTitle;
#OneToMany(mappedBy = "event")
private List<PeopleWhoLiked> peopleWhoLiked;
}
#Entity
public class PeopleWhoLiked {
#EmbeddedId
private PeopleWhoLiked id;
#ManyToOne #MapsId("articleId")
private Article article;
#ManyToOne #MapsId("userId")
private User user;
}
And there is category entity.Every article has one category.
public class Category {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "category_id")
private int id;
#NotEmpty
#Column(name = "categoryName")
private String categoryName;
#OneToMany(mappedBy = "article")
private List<Article> articleList;
}
My Like Table
Article_id User_id
x x
These are both foreign keys to related tables.
With
category.getArticleList(); function i can show articles to users.They can like articles.But the thing is the system doesn't know that if the article was liked by user already. So always like button is active.
Querying (select statement for every article on Like table) is looks like has huge time complexity and overload to the system.) Even if i do how can i post this into thymeleaf th:each statement with only Article object.
I think querying 10 article's like per time with one select statement sounds good .But again how can i pass this to thymeleaf with Article object.
Your problem with performance is caused by additional request for every row.
For 1 select returning 100 rows you make additionals 100 select to database.
If you need display complicated result build view and than map result of view to your #Entity class, which will used only for presentation purpose.

Fetch specific property in hibernate One-to-many relationship

I have two pojo classes with one-to-many relationship in hibernate
CustomerAccountEnduserOrderDetails.class
#Entity #Table(name="customer_account_enduser_order_details")
public class CustomerAccountEnduserOrderDetails implements Serializable{
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name="id")
private Long id;
#ManyToOne(fetch=FetchType.EAGER)
#JoinColumn(name = "product_id", insertable = false, updatable = false)
private CustomerCmsProduct customerCmsProduct;
}
Second is CustomerCmsProduct.class
#Entity
#Table(name="customer_cms_product")
#JsonIgnoreProperties(ignoreUnknown = true)
public class CustomerCmsProduct {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="id")
private Long id;
#Column(name="name")
private String name;
#Column(name="offer_price")
private String offerPrice;
#Column(name="original_price")
private String originalPrice;
#Column(name="discount")
private String discount;
}
Here if I fetch the object of CustomerAccountEnduserOrderDetails class,then i will get the CustomerCmsProduct class also , my problem is that here i want the specific column of CustomerCmsProduct table (not all by default i am getting all) like only id and originalPrice.
How i can do like that projection here?
In the service layer or at a webservice layer( if this is a web project) Create two different classes other than #Entity as DTO(Data Transfer Objects) which helps is data transfer from one layer to the other.
public class CustomerAccountEnduserOrderDetailsPojo {
private List<CustomerCmsProductPojo> productPojoList = new ArrayList<> ();
// getter and setter
}
public class CustomerCmsProductPojo {}
Follow the below steps
Retrieve the #Entity class data by executing the query from service layer.
Iterate over all the fields and copy only required fields to pojo layer
Expose the data to other layers using service method.
This way, we can avoid changing the custom hibernate behavior as it is linked with many parameters like cache, one to many queries that are fired per iteration.
And also, do any customization that you want in this layer. Hope this is multi layered project where you have different layers which servers different purpose.

Resources