Jpa Criteria for ManyToMany and OneToOne relationships - java

I have 3 POJO classes - Link, LinkDetails and Tag.
The relationship between Link and LinkDetails - OneToOne, between LinkDetails and Tag - ManyToMany.
How to use Jpa Criteria, find a list of links with a specified tag name ?
#Entity
public class Link extends AbstractEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column
private String url;
#OneToOne(cascade = CascadeType.ALL)
#PrimaryKeyJoinColumn
private LinkDetails linkDetails;
}
#Entity
public class LinkDetails extends AbstractEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column
private String description;
#JoinTable(name = "link_details_2_tag", joinColumns = { #JoinColumn(name = "link_details_id")}, inverseJoinColumns = { #JoinColumn(name = "tag_id") })
#ManyToMany(targetEntity = Tag.class, fetch = FetchType.LAZY)
private Set<Tag> tags = new TreeSet<Tag>();
}
#Entity
public class Tag extends AbstractEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column
private String name;
}

#Override
public List<Link> getLinksByTag(String tag){
CriteriaBuilder cBuilder = getEntityManager().getCriteriaBuilder();
CriteriaQuery<Link> criteria = cBuilder.createQuery( Link.class );
Root<Link> linkRoot = criteria.from( Link.class );
Join<Link, LinkDetails> linkDetailsJoin = linkRoot.join(Link_.linkDetails);
Join<LinkDetails, Tag> tagJoin = linkDetailsJoin.join(LinkDetails_.tags);
criteria.select(linkRoot);
criteria.where(cBuilder.equal(tagJoin.get(Tag_.name), tag));
TypedQuery<Link> query = getEntityManager().createQuery(criteria);
return query.getResultList();
}

Related

How do I retrieve parent object with child object while having OneToMany bidriectional relationship in spring boot?

I am new to Spring boot. please help me with the below issue:
I am getting only child object data while retrieving using join query..
Below is my child entity class:
#Entity
#Table(name = "tenant_user_configuration")
public class TenantUserConfiguration {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column(name = "config_key")
private String configKey;
#Column(name = "config_value")
private String configValue;
private String system;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name="tenant_user_id",referencedColumnName = "tenant_user_id")
#JsonBackReference
private TenantUser tenantUser;
This is my parent entity class:
#Entity
#Table(name = "tenant_user")
public class TenantUser {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "tenant_user_id")
private int tenantUserId;
#OneToOne
#JoinColumn(name = "tenant_id",referencedColumnName = "tenant_id")
private Tenant tenant;
#Column(name = "user_name")
private String userName;
#Column(name = "password")
private String password;
#Column(name = "enabled")
private boolean enabled;
#OneToMany(mappedBy = "tenantUser",fetch = FetchType.EAGER)
#JsonManagedReference
private Set<TenantUserConfiguration> tenantUserConfiguration = new HashSet<>();

How to map only values of HashMap - Hibernate

I'd like to map only the values of a map to database.
In the example below, in class Holder, there's a map of ID, Entity, being the ID a BigInteger and the entity Item.
I'm doing this because I want fast search and hashmap K,V is good for that.
But, now, the mapping is weird.
The JoinTable holder_items now has 3 columns, holder_id. item_id and item_KEY.
Can I have only older_id and item_Id?
Basically, mapping only items.values() to the current Holder.
#Entity
public class Holder {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinTable(
name = "holder_items",
joinColumns = #JoinColumn(name = "holder_id"),
inverseJoinColumns = #JoinColumn(name = "item_id")
)
private Map<BigInteger, Item> items = new HashMap<>();
//(...)
}
#Entity
public class Item {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(columnDefinition = "BIGINT")
private BigInteger id;
//(...)
}
You could do this mapping without the third table if it is not necessary ofc. Example:
#Entity
public class Holder {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#MapKey(name = "id")
#OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy="holder")
private Map<BigInteger, Item> items = new HashMap<>();
#Entity
public class Item {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(columnDefinition = "BIGINT")
private BigInteger id;
#ManyToOne
private Holder holder;
}
Solution with help of #Anthony
#Entity
public class Holder {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#MapKey(name = "id")
#OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinTable(
name = "holder_items",
joinColumns = #JoinColumn(name = "holder_id"),
inverseJoinColumns = #JoinColumn(name = "item_id")
)
private Map<BigInteger, Item> items = new HashMap<>();
-
#Entity
public class Item {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(columnDefinition = "BIGINT")
private BigInteger id;
}
Results in table holder_items with holder_id and item_id, as desired!

Count all specific properties of entity JPA

I have question. I have 3 entities Book->Part->Page with relationships.
Book.java
#Entity
#Table(name = "Book")
public class Book{
#ID
#Column(name = "id")
private Long id;
#OneToMany
#JoinColumn(name="bookid", referencedColumnName="id")
private Set<Part> parts = new HashSet<Part>;
}
Part.java
#Entity
#Table(name = "Part")
public class Part{
#ID
#Column(name = "id")
private Long id;
#Column(name="bookid")
private Long bookid;
#ManyToMany
#JoinTable(name="partpage",
joinColumns = #JoinColumn(name = "id")
inverseJoinColumns = #JoinColumn(name = "pageid")
private Set<Page> pages = new HashSet<Page>;
}
Page.java
#Entity
#Table(name = "Page")
public class part{
#ID
#Column(name = "pageid")
private Long id;
#Column(name="color")
private String color;
#Column(name="type")
private String type;
}
I have query = "Select b FROM book b". This query returns all books with all relation parts and pages.
What I need.
I need count how many pages with color = green and type = comedy in each Book. Is it possible to do it in one query?
Thank you all.

Select records without parent with Hibernate using Criteria API

How select records without parent with Hibernate using Criteria API?
Here is my Java code for select with parents
getSessionFactory().getCurrentSession().createCriteria(Category.class).add(
Restrictions.eq("parent", new Category(parentId))).list();
Category Java code
#Entity
#Table(name = "CATEGORY")
public class Category implements NamedModel{
#Id
#Column(name = "CATEGORY_ID")
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#OneToOne(cascade = CascadeType.REMOVE, fetch = FetchType.LAZY)
#JoinTable(name = "CATEGORY_RELATIONS",
joinColumns = {
#JoinColumn(name = "CATEGORY_RELATIONS_CATEGORY_ID", referencedColumnName = "CATEGORY_ID")},
inverseJoinColumns = {
#JoinColumn(name = "CATEGORY_RELATIONS_PARENT_ID", referencedColumnName = "CATEGORY_ID")})
private Category parent;
#OneToMany(cascade = CascadeType.REMOVE, fetch = FetchType.EAGER, mappedBy = "parent")
private List<Category> children;//...
}
CategoryRelations Java code
#Entity
#Table(name = "CATEGORY_RELATIONS")
#IdClass(CategoryRelations.CategoryRelationsPrimaryKey.class)
public class CategoryRelations implements Serializable {
#Id
#Column(name = "CATEGORY_RELATIONS_CATEGORY_ID")
private long categoryId;
#Id
#Column(name = "CATEGORY_RELATIONS_PARENT_ID")
private long parentId;
#Entity
#IdClass(CategoryRelationsPrimaryKey.class)
public static class CategoryRelationsPrimaryKey implements Serializable {
private long categoryId;
private long parentId;
}
}
You can use Restriction#isNull(propertyName) function for your requirements.
Restrictions.isNull("parent")

Hibernate annotation mapping, complicated diagram

I have some big problems with making a proper mapping for delivered diagram. It looks like this:
Now, so far I did this, hopefully its ok (ommited getters/setters). You'll notice that USERS has DOMAIN_ID, ignore it as it is not full diagram.
FunctionalityGroup
#Entity
#Table(name = "FUNCTIONALITY_GROUP")
public class FunctionalityGroup implements Serializable
{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "FUNCTIONALITY_GROUP_ID")
private Long functionalityGroupId;
#Column(name = "FUNCTIONALITY_GROUP_NM")
private String functionalityGroupName;
#Column(name = "FUNCTIONALITY_GROUP_DESC")
private String functionalityGroupDesc;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "funcionalityGroupId")
private List<Functionality> functionalityList;
}
Functionality
#Entity
#Table(name = "FUNCTIONALITY")
public class Functionality implements Serializable
{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "FUNCTIONALITY_ID")
private Long functionalityId;
#Column(name = "FUNCTIONALITY_NM")
private String functionalityGroupName;
#Column(name = "FUNCTIONALITY_DESC")
private String functionalityGroupDesc;
#Column(name = "FUNCTIONALITY_GROUP_ID")
private Long funcionalityGroupId;
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable(name = "ROLE_FUNCTIONALITY",
joinColumns = {#JoinColumn(name = "FUNCTIONALITY_ID")},
inverseJoinColumns = {#JoinColumn(name = "ROLE_ID")})
private List<Role> roleList;
}
Role
#Entity
#Table(name = "ROLE")
public class Role implements Serializable
{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "ROLE_ID")
private Integer roleId;
#Column(name = "ROLE_NM")
private String roleName;
#Column(name = "ROLE_DESC")
private String roleDesc;
#Column(name = "OBJECT_TYPE")
private String objectType;
#ManyToMany(fetch = FetchType.LAZY, mappedBy = "roleList")
private List<Functionality> functionalityListy;
}
Users
#Entity
#Table(name = "USERS")
public class Users implements Serializable
{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "USER_ID")
private Long userId;
#Column(name = "USER_DESC")
private String userDesc;
#Column(name = "FIRST_NM")
private String firstNM;
#Column(name = "LAST_NM")
private String lastNM;
#Column(name = "IS_ENABLED")
private String isEnabled;
}
I have no idea how Role_Member and Role_Member_Entry should be mapped and handled withing object world, could somebody give me some hits? Thanks!
Normally I'd connect Users with Role as Many to Many, but the entity Role_Member_Entry ruins everything.

Categories