Selecting specific columns in many to many relationship with JPA - java

I have to Models for two Entities in Database. Model User and Model Role. These two entities have a many-to-many relationship. In the model files I have class User.java:
#Entity
#Table(name = "User")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
private String username;
private String password;
private String name;
#ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinTable(
name = "role_user",
joinColumns = {#JoinColumn(name = "user_id")},
inverseJoinColumns = {#JoinColumn(name = "role_id")})
private Set<Role> roles;
//getters and setters
}
and I have class Role.java:
#Entity
#Table(name = "Role")
public class Role {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="id")
private int id;
private String role;
#ManyToMany(mappedBy = "roles", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Set<User> users;
//getters and setters
}
I also have the repositories/DAO for them:
public interface UserRepository extends JpaRepository<User, Integer>{}
and
public interface RoleRepository extends JpaRepository<Role, Integer> {}
Now when I fetch all results from class Role it returns all the columns from Entity User, how can I specify that I want only the column name from User Entity? Should I build another model only with the columns I need or there is any simple way to select specific columns?

Related

Hibernate One to Many relation- Child table not updating

Here I am adding a list of new orders to a specific user. While adding orders to a specific user, it returns success status, but still my database is empty. Why the data is not getting added...?
Users
#Entity
Class Users{
#Id
private int id;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "user")
private List<Orders> orders;
}
Orders
#Entity
Class Orders{
#Id
private int id;
private Date orderDate;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "user_id")
private User user;
}
Repository
public ResponseEntity<String> addOrder(int userId,List<Orders> orders) throws UserNotFound{
User user =userRepository.findById(userId).orElse(null);
if(user==null) throw new UserNotFound("User Not Found");
for(Orders o:orders){
o.setOrderDate(new Date("....."));
}
user.getOrders().addAll(orders);
userRepository.save(user);
}
Try to add cascade persist to your relation specification:
#Entity
Class Users{
#Id
private int id;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "user", cascade={CascadeType.PERSIST})
private List<Orders> orders;
}

Spring Boot JPA how to retrieve data from a ManyToMany table?

I am learning Spring boot.
Now I have ManyToMany relationship with a User entity and a Team entity.
So an user can have several teams and a team can have several users.
#Entity
public class User {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="id", nullable =false, updatable = false)
private Long id;
#ManyToMany
#JoinTable(
name = "team_have",
joinColumns = #JoinColumn(name = "id"),
inverseJoinColumns = #JoinColumn(name = "teamId"))
List<Team> haveTeams;
This is the Team entity:
#Entity
#Table(name="TEAM")
public class Team {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long teamId;
#OneToMany(cascade = CascadeType.ALL, mappedBy="team")
private List<Task> tasks;
This is my repository:
public interface TeamRepository extends CrudRepository<Team, Long>{
List<Team>findByName(String name);
}
How can I find all teams which belonged to one user?
User already have mapped with List<Team>, you need to use UserRepository instead of TeamRepository.
public interface UserRepository extends CrudRepository<User, Long>{
User findByName(String name);
}
Here, you will get one user and that user have all teams which he belongs to. (Assuming username is unique)
OR
If you are having bidirectional Many-to-Many (Team also mapped Lis<User>) like following
#Entity
#Table(name="TEAM")
public class Team {
....
#ManyToMany(cascade = CascadeType.ALL, mappedBy="haveTeams")
private List<User> users;
Then you can define query method like following to get all teams for one user,
public interface TeamRepository extends CrudRepository<Team, Long>{
List<Team> findByUsers(User user);
}
The best way to build the connection between them would be to use a bi-directional relationship, like this:
User Entity
#Entity
#Table(name = "user")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
/* #Column(name = "id", nullable = false, updatable = false) You don't need this,
the name is taken from the name of the variable and it cannot be null since you
have #GeneratedValue */
private Long id;
#ManyToMany(fetch = LAZY, cascade = CascadeType.PERSIST)
#JoinTable(
name = "user_team", // I would name this user_team since the user can have many teams, and vice versa
joinColumns = #JoinColumn(name = "user_id" , referencedColumnName = "id"),
inverseJoinColumns = #JoinColumn(name = "team_id", referencedColumnName = "id"))
Set<Team> teams = new HashSet<>();
}
Team Entity
#Entity
#Table(name="team")
public class Team {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long teamId;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "team")
private List<Task> tasks;
#ManyToMany(mappedBy = "teams", fetch = LAZY, cascade = CascadeType.PERSIST)
private Set<User> users = new HashSet<>();
}
Team Repo
public interface TeamRepository extends CrudRepository<Team, Long>{
#Query(value = "SELECT * FROM team t1 INNER JOIN user_team t2 ON t1.id = t2.team_id WHERE t2.user_id = ?1 ")
List<Team> findAllByUserId(long userId);
}
Example of use:
List<Team> teams = teamRepo.findAllByUserId(1);
A great tutorial:
https://attacomsian.com/blog/spring-data-jpa-many-to-many-mapping

Java JPA Realtions

I am doing an application where I need 2 entities: User and Car.
public class User{
private long id;
private String name;
}
public class Car{
private long id;
private User firstUser;
private User secondUser;
}
So my table cars_info info will contain
RENT(date), FIRST_USER(id), SECOND_USER(id)
How do I connect this using hibernate? I need unidirectional relation. I tried OneToOne, ManyToOne but neither of that works.
Check that you're properly naming the column on your CAR table vs the reference column on the USER table. Example below:
#Entity
#Table(name = "USER")
public class User {
#Id
#Column(name = "USER_ID")
private long id;
#Column(name = "NAME")
private String name;
}
#Entity
#Table(name = "CAR")
public class Car {
#Id
#Column(name = "CAR_ID")
private long id;
#ManyToOne
#JoinColumn(name = "FIRST_USER_ID", referencedColumnName = "USER_ID")
private User firstUser;
#ManyToOne
#JoinColumn(name = "SECOND_USER_ID", referencedColumnName = "USER_ID")
private User secondUser;
}

Hibernate create alias on many to many list

I have four class; UserGroup, UserAccount, Role, UserGroupRoleRelation and my db is IBM DB2
#Entity
#Table(name = "USER_GROUP")
public class UserGroup implements Serializable {
#Id
#Column(name = "USER_GROUP_ID")
#GeneratedValue
private Long id;
......
..
#OneToMany(mappedBy = "userGroup", cascade = CascadeType.ALL, orphanRemoval = true)
private List<UserGroupRoleRelation> userAccountsRole = new ArrayList<UserGroupRoleRelation>();
}
#Entity
#Table(name = "ROLE")
public class Role implements Serializable {
#Id
#Column(name = "ROLE_ID")
#GeneratedValue
private Long id;
......
#OneToMany(mappedBy = "role")
private List<UserGroupRoleRelation> userAccountInGroup = new ArrayList<UserGroupRoleRelation>();
}
#Entity
#Table(name = "USER_GROUP_ROLE_LINE", uniqueConstraints = #UniqueConstraint(columnNames = { "ROLE_ID", "USER_GROUP_ID" }))
public class UserGroupRoleRelation {
#Id
#GeneratedValue
#Column(name = "RELATION_ID")
private Long relationId;
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name = "USER_ACCOUNT_USER_GROUP_ROLE_LINE", joinColumns = { #JoinColumn(name = "RELATION_ID") }, inverseJoinColumns = { #JoinColumn(name = "USER_ID") }, uniqueConstraints = #UniqueConstraint(columnNames = { "USER_ID", "RELATION_ID" }))
private List<UserAccount> userAccountList = new ArrayList<UserAccount>();
#ManyToOne
#JoinColumn(name = "USER_GROUP_ID")
private UserGroup userGroup;
#ManyToOne
#JoinColumn(name = "ROLE_ID")
private Role role;
}
#Entity
#Table(name = "USER_ACCOUNT")
public class UserAccount implements Serializable {
#Id
#Column(name = "USER_ID")
#GeneratedValue
private Long id;
.....
#ManyToMany(mappedBy = "userAccountList", cascade = CascadeType.ALL)
private List<UserGroupRoleRelation> rolesInGroup = new ArrayList<UserGroupRoleRelation>();
}
I wanna find usergroups of a useraccount and i prepared a method with criteria. its like;
#Override
#Transactional
public List<UserGroup> findUserGroupOf(UserAccount userAccount) {
Criteria criteria = getSession().createCriteria(UserGroup.class);
criteria.createAlias("userAccountsRole", "userAccountsRole");
criteria.add(Restrictions.eq("userAccountsRole.userAccountList", userAccount));
return criteria.list();
}
But when i try to get result of that method, DB2 gives to me DB2 SQL Error: SQLCODE=-313, SQLSTATE=07004, SQLERRMC=null, DRIVER=3.63.75
Probably its about creating alias on many to many relation. I dont know what should i do to create alias on many to many. How can I get result of that function?
Thank
#Override
#Transactional
public List<UserGroup> findUserGroupOf(UserAccount userAccount) {
Criteria criteria = getSession().createCriteria(UserGroup.class);
criteria.createAlias("userAccountsRole", "userAccountsRole");
criteria.createAlias("userAccountsRole.userAccountList", "userAccountList");
criteria.add(Restrictions.eq("userAccountList.id", userAccount.getId()));
return criteria.list();
}
It works for me. I mean criteria on "id". But I don't understand why I cant check equality on object instead of id when there is ManyToMany list
It is not of creating alias. You are passing an object to hibernate on which it can not make any criteria. You need to create bidirectional mapping for that.Or else if you your requirement is just to fetch the the list of UserAccountList of particular UserGroup class you can follow the below code.
#Override
#Transactional
public List<UserGroup> findUserGroupOf(long userGroupId) {
Criteria criteria = getSession().createCriteria(UserGroup.class);
criteria.add(Restrictions.eq("id",userGroupId));
criteria.createAlias("userAccountsRole", "uar");
criteria.setFetchMode("uar.userAccountList",FetchMode.JOIN);
return criteria.list();
}

How to create join table with JPA annotations?

I need to create a join table in my database using JPA annotations so the result will be this:
So far I just implemented 2 entities:
#Entity
#Table(name="USERS", schema="ADMIN")
public class User implements Serializable {
private static final long serialVersionUID = -1244856316278032177L;
#Id
#Column(nullable = false)
private String userid;
#Column(nullable = false)
private String password;
public String getUserid() {
return userid;
}
public void setUserid(String userid) {
this.userid = userid;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
#Entity
#Table(name="GROUPS", schema="ADMIN")
public class Group implements Serializable {
private static final long serialVersionUID = -7274308564659753174L;
#Id
#Column(nullable = false)
private String groupid;
public String getGroupid() {
return groupid;
}
public void setGroupid(String groupid) {
this.groupid = groupid;
}
}
Should i create another entity called USER_GROUP or i can just add some annotations, so the join table will be created automatically when i run create tables from entities(ORM)?
How should i annotate my entities to achieve the same as in the image?
You definitely shouldn't create User_Group entity as it's more the underlying database representation than the object oriented one.
You can achieve the join table by defining something like:
#Entity
#Table(name="USERS", schema="ADMIN")
public class User implements Serializable {
//...
#ManyToOne
#JoinTable(name="USER_GROUP")
Group group;
#Entity
#Table(name="GROUPS", schema="ADMIN")
public class Group implements Serializable {
//...
#OneToMany(mappedBy="group")
Set<User> users;
Edit: If you want to explicitly set the names of the columns you could use #JoinColumn elements as shown below:
#ManyToOne
#JoinTable(name="USER_GROUP",
joinColumns = #JoinColumn(name = "userid",
referencedColumnName = "userid"),
inverseJoinColumns = #JoinColumn(name = "groupid",
referencedColumnName = "groupid"))
Group group;
I would implement it this way:
#Entity
#Table(name="GROUPS", schema="ADMIN")
public class Group implements Serializable {
#OneToMany
#JoinTable(name = "USER_GROUP",
joinColumns = #JoinColumn(name = "groupid"),
inverseJoinColumns = #JoinColumn(name = "userid"))
private List<User> users;
}
Solution suggested by #PedroKowalski should work too, but then you'll have to keep a reference to Group entity in your User entity which is not always possible.
To have the same annotations like in your diagram you can do this in your User class:
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable(name = "USER_GROUP",
joinColumns = { #JoinColumn(name = "userid") },
inverseJoinColumns = { #JoinColumn(name = "groupid") })
private List<Group> grups;
in your group class
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable(name = "USER_GROUP",
joinColumns = { #JoinColumn(name = "groupid") },
inverseJoinColumns = { #JoinColumn(name = "userid") })
private List<User> users;
I'm wondering what is the point to create a Join Table in this way, considering that we can't access directly for queries?
JPA doesn't allow to make queries directly to the Join Table, so if the user want to do an operation on USER_GROUP, he has to creare a normal join query between users and groups; due to this, the join table USER_GROUP is useless.

Categories