Issue
I am building a simple CRUD app using SpringBoot
, Hibernate
and JPA
. I am very new to using Hibernate and just figuring it out.
Furthermore, I have a many-to-many association and as a result to that association a third table is created.
The third table is consisted of two primary keys user_id
and sport_id
.
I am having a hard time populating that table.
I am sending JSON object via Postman like RequestBody
:
[
{
"id": 4,
"sport_id": 1,
"user_id": 2
}
]
SportUsersController.java
@PostMapping("/sportsUsers")
public void saveSportsUsers(@RequestBody List<SportUser> sportUserList){
this.sportUserService.saveSportUser(sportUserList);
}
SportUsersDaoImpl.java
@Override
public void saveSportUser(List<SportUser> sportUserList) {
for (SportUser sportUser : sportUserList){
User user = (User) entityManager.createQuery("from Users u where u.id = :sportUser.getUser()")
.setParameter("User", sportUser.getUser())
.getSingleResult();
Sport sport = (Sport) entityManager.createQuery("from Sport s where s.id = :sportUser.getSport()")
.setParameter("Sport", sportUser.getSport())
.getSingleResult();
sportUser = (SportUser) entityManager.createStoredProcedureQuery("saveSportUser")
.registerStoredProcedureParameter(1, Long.class, ParameterMode.IN)
.registerStoredProcedureParameter(2, Long.class, ParameterMode.IN)
.setParameter(1, sport)
.setParameter(2, user);
entityManager.merge(sportUser);
}
}
I was trying to do something like this but of course query from Users u where u.id = :sportUser.getUser()
is not working because of u.id = :sportUser.getUser()
is not correct syntax.
SportUser.java
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Getter
@Setter
@Entity(name = "Sport_Users")
@ApiModel(description = "All details about sport an users")
public class SportUser {
/**
* unique SportUsers number, auto generated
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
/**
* object sport
*/
@ManyToOne(fetch = FetchType.LAZY, targetEntity = Sport.class)//load it on-demand
@JoinColumn(name = "sport_id", referencedColumnName = "id")
private Sport sport;
/**
* object user, user who plays sport
*/
@ManyToOne(fetch = FetchType.LAZY, targetEntity = User.class)//load it on-demand
@JoinColumn(name = "user_id", referencedColumnName = "id")
private User user;
}
I am not sure how to write query to get id from list for User and for Sport.
Any advice appreciated!
Solution
I found the working solution I was looking for thanks to @kameshsr and @Philipp directions.
So I changed my entities to look like this:
User.java
@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinTable(
name = "Sport_Users",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "sport_id"))
private Set<Sport> sports = new HashSet<>();
Sport.java
@JsonIgnore
@ManyToMany(fetch = FetchType.LAZY, mappedBy = "sports")
Set<User> user = new HashSet<>();
I want to be able to save a list of users at one go and be able to connect user to sport. So I used java streams to do that.
This is how my code looks like:
@Override
public void saveUser(List<User> newUsers) {
for(User user : newUsers) {
user.getSports()
.addAll(user.getSports().stream()
.map(s -> { Sport sport = sportDao.getSportById(s.getId());
sport.getUser().add(user);
return sport;
}).collect(Collectors.toList()));
entityManager.merge(user);
}
}
Hope that it helps someone with same problem :)
Answered By - user9347049