Reputation: 1595
Context
I'm trying to create an API with SpringBoot, Hateoas, store data into H2 database and manage it with JPA.
I have 2 entities : Mission
and User
.
Several users are assigned to a mission. And users can be assigned to different missions.
I use @ManyToMany
annotation to create an associative table.
Objectives
My goal is to create some requests as :
IP/missions/123456/users
: Get all users assigned to mission 123456
IP/missions/456789
: Assigned users to mission 456789
Code
Entities
@Entity
public class Mission {
@Id
private String missionid;
private String missionname;
private Date start;
private Date end;
@ManyToMany(mappedBy = "missions")
@JoinTable(name = "missions_users",
joinColumns = @JoinColumn(name = "missionid"),
inverseJoinColumns = @JoinColumn(name = "userid")
)
private Set<User> users = new HashSet<>();
private int status;
public Mission() {
}
public Mission(String name, Date start, Date end) {
this.namemission = name;
this.start = start;
this.end = end;
this.status = 0;
}
}
@Entity
public class User {
@Id
private String userid;
private String nameuser;
@ManyToMany
private Set<Mission> missions = new HashSet<>();
public User() {
}
public User(String name) {
this.nameuser = name;
}
}
Resources
@RepositoryRestResource(collectionResourceRel = "mission")
public interface MissionResource extends JpaRepository<Mission, String> {
}
@RepositoryRestResource(collectionResourceRel = "user")
public interface UserResource extends JpaRepository<User, String> {
}
RestController
@RestController
@RequestMapping(value = "/missions", produces = MediaType.APPLICATION_JSON_VALUE)
@ExposesResourceFor(Mission.class)
public class MissionRepresentation {
private final MissionResource missionResource;
private final UserResource userResource;
public MissionRepresentation(MissionResource missionResource, UserResource userResource) {
this.missionResource = missionResource;
this.userResource = userResource;
}
// mapping
}
SQL script to fill database
INSERT INTO mission (missionid, namemission, start, end, status) VALUES ('de7d9052-4961-4b4f-938a-3cd12cbe1f82', 'mission 1', '2019-02-11', '2019-02-13', 0)
INSERT INTO mission (missionid, namemission, start, end, status) VALUES ('425e7701-02c6-4de3-9333-a2459eece1c8', 'mission 2', '2019-02-10', '2019-02-15', 0)
INSERT INTO user (userid, nameuser) VALUES ('0dee5423-6bd9-4014-a690-0993b3cb5f3b', 'user 1')
INSERT INTO user (userid, nameuser) VALUES ('8e70ca41-8766-4188-bf37-3d9a0aae941d', 'user 2')
INSERT INTO user (userid, nameuser) VALUES ('75cb846a-3a7b-4116-8d8a-7778916dff8c', 'user 3')
INSERT INTO missions_users(missionid, userid) VALUES ('de7d9052-4961-4b4f-938a-3cd12cbe1f82', '0dee5423-6bd9-4014-a690-0993b3cb5f3b')
INSERT INTO missions_users(missionid, userid) VALUES ('de7d9052-4961-4b4f-938a-3cd12cbe1f82', '8e70ca41-8766-4188-bf37-3d9a0aae941d')
INSERT INTO missions_users(missionid, userid) VALUES ('425e7701-02c6-4de3-9333-a2459eece1c8', '8e70ca41-8766-4188-bf37-3d9a0aae941d')
INSERT INTO missions_users(missionid, userid) VALUES ('425e7701-02c6-4de3-9333-a2459eece1c8', '75cb846a-3a7b-4116-8d8a-7778916dff8c')
Results
Currently I try to do GET
requests, but in the future I will have to do POST
/PUT
/... requests.
Request : http://localhost:8082/mission/de7d9052-4961-4b4f-938a-3cd12cbe1f82
{
"missionid": "de7d9052-4961-4b4f-938a-3cd12cbe1f82",
"namemission": "mission 1",
"users": [
{},
{}
],
"status": 0,
"start": "2019-02-10T23:00:00.000+0000",
"end": "2019-02-12T23:00:00.000+0000"
}
Request : http://localhost:8082/mission/de7d9052-4961-4b4f-938a-3cd12cbe1f82
{
"missionid": "de7d9052-4961-4b4f-938a-3cd12cbe1f82",
"namemission": "mission 1",
"users": [
"user 1",
"user 2"
],
"status": 0,
"start": "2019-02-10T23:00:00.000+0000",
"end": "2019-02-12T23:00:00.000+0000"
}
Request : http://localhost:8082/mission/de7d9052-4961-4b4f-938a-3cd12cbe1f82/users
{
"user 1",
"user 2"
}
I don't know how to write my method to get only users names...
@GetMapping(value = "/{missionId}/users")
public ResponseEntity<?> getUsersByMission(@PathVariable("missionId") String missionId) {
Mission mission = this.missionResource.findById(missionId).get();
return new ResponseEntity<>(????, HttpStatus.OK);
}
A solution is to use a list of String instead of a list of User?
Conclusion
Someone can help me to have expected results please? Thanks.
EDIT 1: Result for @LppEdd answer
[
{
"userid": "0dee5423-6bd9-4014-a690-0993b3cb5f3b",
"nameuser": "user 1",
"missions": []
},
{
"userid": "8e70ca41-8766-4188-bf37-3d9a0aae941d",
"nameuser": "user 2",
"missions": []
}
]
Upvotes: 0
Views: 58
Reputation: 21172
It should pretty easy actually. You were almost there.
JPA will handle the User
objects creation for you. Just expose your Set<User>
to the outer world.
public class Mission {
...
public Set<User> getUsers() {
return users;
}
public void setUsers(final Set<User> users) {
this.users = users;
}
...
}
Inside your @RestController
, you can then get a hold on, and return the Set
.
public ResponseEntity<List<String>> getUsersByMission(@PathVariable("missionId") String missionId) {
final Optional<Mission> mission = this.missionResource.findById(missionId);
if (mission.isEmpty()) {
// Handle the "mission not found" case
}
final List<String> names =
mission.get().getUsers()
.stream()
.map(user -> user.getNameUser())
.collect(Collectors.toList());
return ResponseEntity.ok().body(names);
}
To handle bidirectional @ManyToMany
associations, you need to specify the mappedBy
attribute, which will point to the Mission#users
field.
@ManyToMany(mappedBy = "users")
private Set<Mission> missions = new HashSet<>();
Upvotes: 1