Why unidirectional instead of bidirectional? - java

So I'm following a Spring Boot tutorial online, and I have two Java classes, which are entities: Order and Address:
Order.java:
public class Order {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
// more properties
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "shipping_address_id", referencedColumnName = "id")
private Address shippingAddress;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "billing_address_id", referencedColumnName = "id")
private Address billingAddress;
}
Address.java:
public class Address {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
// more properties
#OneToOne
#PrimaryKeyJoinColumn
private Order order;
}
Is this a bidirectional relationship (even though neither entity has a #JoinColumn with a mappedBy attribute) or is this two unidirectional relationships, Order->Address and Address->Order?

Related

“Illegal attempt to map a non collection as a #OneToMany, #ManyToMany or #CollectionOfElements” SpringBoot

i have three entites named depense ,benifice and categories , when i want to get the benefice_C and the Depenese_C in the category entity .this error displayed to me
“Illegal attempt to map a non collection as a #OneToMany, #ManyToMany or #CollectionOfElements” SpringBoot
Depens Entities
> #Entity
#Getter
#Setter
#Table(name="depense")
public class Depense {
#Id #GeneratedValue
#Column(name = "id_etab")
private Long idEtab;
#ManyToOne
#JoinColumn(name = "personnel_id")
private Personnel personnel;
#ManyToOne
#JoinColumn(name = "CATD")
private Categories categoriesD;
Benfice Entities
> public class Benifice {
#Column(name = "id_etab")
private Long idEtab;
#ManyToOne
#JoinColumn(name = "inscrit_id")
private Inscrit inscrit;
#ManyToOne
#JoinColumn(name = "be_C")
private Categories benificeC;
Categorie entite
> public class Categories implements Serializable {
#Id #GeneratedValue(strategy = GenerationType.IDENTITY)
private Long idCat;
#OneToMany(mappedBy = "categoriesD", fetch = FetchType.LAZY)
private Depense depense;
#OneToMany(mappedBy = "benificeC", fetch = FetchType.LAZY)
private Benifice benifice;
Your #OneToMany mapping is not correct.
You would need a List/Set/Collection of Objects if you map OneToMany.
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long idCat;
#OneToMany(mappedBy = "categoriesD", fetch = FetchType.LAZY)
private List<Depense> depense;
#OneToMany(mappedBy = "benificeC", fetch = FetchType.LAZY)
private List<Benifice> benifice;

How to set value for all OneToMany entities?

I have an ClientUser entity with #OneToMany field customField:
#Entity
#Data
public class ClientUser {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
private long id;
#OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinTable(
name = "client_user_custom_field",
joinColumns = #JoinColumn(name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = #JoinColumn(name = "field_id", referencedColumnName = "id"))
private Collection<ClientFieldValue> customFields;
}
And a ClientFieldValue entity:
#Entity
#Data
public class ClientFieldValue {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
private long id;
private String value;
}
How can I create ClientFieldValue's for all existing ClientUser?
I know that I can do smth like:
final Iterable<ClientUser> clientUsers = userRepository.findAll();
clientUsers.forEach(clientUser ->
clientUser.setCustomFields(Collections.singleton(new ClientFieldValue())));
userRepository.saveAll(clientUsers);
But I don't want to query all and save them after set.
Is there another way to do this?

Mutiple #ManyToMany on a single Entity causes Cross Join

I have a User Entity.
#Entity
#Table(name = "t_login_user")
public class User extends Auditable<Long> implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "user_id")
private Long id;
#Column(name = "user_uid")
private String userUid;
#Column(name = "user_name")
private String userName;
#OneToOne(fetch = FetchType.EAGER, optional = false)
#JoinColumn(name="primary_role_id")
private Role primaryRole;
#ManyToMany(fetch = FetchType.EAGER)
#JoinTable(name = "t_login_user_role_map", joinColumns = #JoinColumn(name = "user_id"), inverseJoinColumns = #JoinColumn(name = "role_id"))
private List<Role> roles;
}
My Role Entity is
#Entity
#Table(name = "t_login_role")
public class Role extends Auditable<Long> implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="role_id")
private Long roleId;
#Column(name="role_code")
private String roleCode;
#ManyToMany(fetch = FetchType.EAGER)
#JoinTable(name = "t_login_role_priv_map", joinColumns = #JoinColumn(name = "role_id"), inverseJoinColumns = #JoinColumn(name = "priv_id"))
private List<Privilege> privileges;
#ManyToMany(fetch = FetchType.EAGER)
#JoinTable(name = "t_login_role_menu_map", joinColumns = #JoinColumn(name = "role_id"), inverseJoinColumns = #JoinColumn(name = "menu_id"))
private List<Menu> menus;
}
My Menu Entity is
#Entity
#Table(name = "t_login_menu")
public class Menu extends Auditable<Long> implements Serializable{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="id")
private Long id;
#Column(name="menu_text")
private String menuText;
#Column(name="menu_icon")
private String menuIcon;
#Column(name="menu_url")
private String menuURL;
}
As you can see my Role has multiple Privileges and Multiple Menus. The problem I face is that when I have a code like
LoggedinUser liu = (LoggedinUser)authentication.getPrincipal();
List<Menu> menus = liu.getPrimaryRole().getMenus();
If I have two privileges say READ_DATA and WRITE_DATA
And three Menus 1. HOME 2.USER 3.PROFILE
my menus variable has a value of [HOME,HOME,USER, USER, PROFILE, PROFILE] (i.e. 2 privileges * 3 Roles)
I suspect that this is due to my Role entity having more than one #ManyToMany annotations.
I tried to search online and Stackoverflow but no results.
Anybody face this issue? Am i doing something fundamentally wrong?
Okay. I understand where the cross join happens. Since both the ManyToMany are being EAGER loaded, this is where the Cross Join Happens.
If I change to LAZY Load then the issue disappears. Slight performance hit on LAZY load, but thats fine since I do it only once and store the result in the session.

JPA: OneToMany relationship with multiple mappedBy attributes

I'm having a problem to map a relationship between instances of one single entity. Let me give you the JPA entities first.
Article entity
#Entity
#Table(name = "article")
public class Article {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "article", orphanRemoval = true)
private Collection<Keyword> keywords;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "article1", orphanRemoval = true)
private Collection<RelatedArticles> relatedArticles;
#Column(name = "content", nullable = false)
#Lob
private String content;
...
}
RelatedArticle entity
#Entity
#Table(name = "related_articles")
public class RelatedArticles {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#JoinColumn(name = "article1_id")
#ManyToOne(optional = false)
private Article article1;
#JoinColumn(name = "article2_id")
#ManyToOne(optional = false)
private Article article2;
private Float weightedJaccardIndex;
...
}
Further explanation
An article can be related to other articles which is realized by the RelatedArticle entity. The article can be referenced by article1 or article2. That means the collection relatedArticles in Article should contain all instances of RelatedArticle where the ID either matches article1 or article2.
Question
How can I map a single collection of RelatedArticles in my Article entity where the origin Article is either article1 or article2?
Alternative solutions are welcome!

spring-data-rest, manytomany relation with join table

Is it possible to expose a manytomany relationship that uses a join entity (that contains extra data columns), below is my entities;
I'm trying to get 'purchases' to show in REST, I've put in 'products' as an example of a working REST mapping;
#Entity
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, targetEntity = Purchase.class, orphanRemoval = true)
#JoinColumn(name = "user_id", updatable = false)
private List<Purchase> purchases = new ArrayList<>();
#ManyToMany
#JoinColumn(name = "user_id", updatable = false)
private List<Product> products = new ArrayList<>();
}
#Entity
public class Product {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
}
#Entity
public class Purchase implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
Long id;
#ManyToOne
#JoinColumn(name = "user_id", referencedColumnName = "id")
private User user;
#ManyToOne(targetEntity = Prodect.class)
#JoinColumn(name = "product_id", referencedColumnName = "id")
private Product product;
#Column(name = "purchase_date")
private Date purchaseDate;
}
So if i send the REST call;
[GET http://localhost:8080/webapp/users/1]
It returns links for [http://localhost:8080/webapp/users/1/products] but not for [http://localhost:8080/webapp/users/1/purchases]
worked out what the issue was; I need to create a JpaRepository for the Purchase entity. Soon as I added that, the REST links for purchases are available.

Categories