Reputation: 345
I have a User, and the user has Expenses. In expenses table I want to have the expense id, the user who made the expense and the amount of expense. In the user table I want user id, his username, his current balance and list of all expenses he's made.
I want to join those 2, but I don't know how to correctly reference user, therefore user form Expense class is always null.
First, I send post request to create a user:
{
"username":"abcd",
"balance":"100"
}
then I want to create an expense, but here I'm not sure how to correctly send a User:
{
"username":"abcd",
"id":"1",
"balance":"100",
"amount":"20"
}
and this doesn't work, then I tried like this:
{
"User":{
"username":"abcd",
"id":"1",
"balance":"100"
},
"amount":"20"
}
and that didn't work either.
This is the User class:
@Entity
@Table(name = "Users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotBlank(message = "Username is mandatory")
private String username;
private Double balance = 0.0;
@OneToMany(mappedBy = "user")
private List<Expense> expenses;
...
I removed getters and setters from here.
Here is the Expense class:
@Entity
@Table(name = "Expenses")
public class Expense {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn(name = "user_id")
private User user;
private Double amount;
...
For saving the expense I use .save()
from JpaRepository<Expense, Long>
and for retrieveing everyting I use .findAll()
.
The result is always the same: get for all expenses gives
{
"id": 1,
"user": null,
"amount": 20
}
and get for all users gives
{
"id": 1,
"username": "abcd",
"balance": 100,
"expenses": []
}
Now I'm not sure whether I'm sending the requests the wrong way or joining the tables the wrong way or both.
EDIT: here is ExpenseController
:
@RestController
public class ExpenseController {
@Autowired
IExpenseService expenseService;
@GetMapping("/expenses")
public List<Expense> findExpenses() {
return expenseService.findAll();
}
@PostMapping("/expenses")
public void createNewExpense(@RequestBody Expense expense) {
expenseService.createNewExpense(expense);
}
}
createNewUser(...)
from ExpenseService
@Override
public void createNewExpense(Expense expense) {
repository.save(expense);
}
and ExpenseRepository
:
@Repository
public interface ExpenseRepository extends JpaRepository<Expense, Long> {
}
UserController
:
@RestController
public class UserController {
@Autowired
IUserService userService;
@GetMapping("/users")
public List<User> findUsers() {
return userService.findAll();
}
@GetMapping("/users/{id}")
public User findUserById(@PathVariable Long id) {
return userService.findById(id);
}
@PostMapping("/users")
public ResponseEntity<Object> createUser(@RequestBody User user) {
if (userService.checkIfUsernameIsTaken(user)) {
Map<String, Object> response = new HashMap<>();
response.put("status", HttpStatus.NOT_ACCEPTABLE);
response.put("errors", "Username is already taken");
response.put("timestamp", new Date());
return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST);
} else {
userService.createNewUser(user);
User currentUser = userService.findById(userService.findByUsername(user.getUsername()));
Map<String, Object> response = new HashMap<>();
response.put("id", currentUser.getId());
response.put("username", currentUser.getUsername());
response.put("balance", currentUser.getBalance());
response.put("expenses", currentUser.getExpenses());
return new ResponseEntity<>(response, HttpStatus.OK);
}
}
@DeleteMapping("/users/{id}")
public void deleteUser(@PathVariable Long id) {
userService.deleteUser(id);
}
@PutMapping("/users/{id}/{balance}")
public void updateBalance(@PathVariable Long id, @PathVariable Double balance) {
userService.updateBalance(id, balance);
}
}
the rest of the User model is the same as the Expense model.
Upvotes: 1
Views: 2706
Reputation: 49
Try to send post request with this payload (field 'user' begins with a small letter), and i think the 'id' field in user object should be enough
{
"user":{
"username":"abcd",
"id":"1",
"balance":"100"
},
"amount":"20"
}
EDIT: Also you need to add @JsonIgnoreProperties("expenses") to your Expense entity to prevent jackson from recursive reading json
@Entity
@Table(name = "Expenses")
public class Expense {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@JsonIgnoreProperties("expenses")
@ManyToOne
@JoinColumn(name = "user_id")
private User user;
private Double amount;
.....
Upvotes: 1