I'm using JPA2 and Springboot2X. Trying to define a simple one-to-one relationship in User
and Account
tables.
User
is the parent while Account
is the child. The relationship is from parent to child. Followed this.
User
table has a column account_no
to hold the account number which is the primary key of the Account
table. So User
holds the foreign key.
@Entity
public class Account extends AbstractEntity implements Serializable{
// fields like account#, balance etc goes here..
@OneToOne (fetch = FetchType.LAZY)
private User user;
}
@Entity
public class User extends AbstractEntity implements Serializable{
// Other fields related to user entity go here ..
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "account_no", referencedColumnName = "account_number")
private Account account;
}
Saving is working properly. But when I fetch a user ( User user = userRp.findByUserID(userid);
), I get data from both tables. My question is when I define fetch = FetchType.LAZY
why the account table data is fetching? I only want the user data to be in the output as when I run the select query in the User
table.
Output :
{
"id": 1,
"userID": "xxxxx",
"firstName": "Dsd",
"llastName": "cccc",
"email": "danqsaa@brown",
"creation_date": "2021-12-19 19:41",
"modified_date": "2021-12-19 19:41",
"account": {
"id": 2,
"accountNo": 6848982326,
"balance": 4000.0,
"creationUser": "xxx",
"creation_date": "2021-12-19 19:41",
"modified_date": "2021-12-19 19:41",
"transactions": []
}
}
Added below RestController, Service, and Repo details.
@RestController
public class UserController {
@GetMapping("/users/{userID}")
public ResponseEntity<Object> getUser(@PathVariable("userID") String userID){
return new ResponseEntity<>(userServiceImpl.getUserByID(userID), HttpStatus.OK));
}
}
@Service
public class UserService {
// injected user repo
public User getUserByID(String userID){
return userRepo.findByUserID(userID);
}
}
public interface UsersRepository extends CrudRepository<User, String> {
User findByUserID(String userID);
}
Santiago Trujillo
It's unfortunate that the question is misleading and it takes many comments to find out what you're asking. Finally I understand - you see the field in JSON and you don't want to. This is a purely Jackson-related question and Hibernate has nothing to do with it.
There are several ways you can take:
There's a good reason we don't use our Entities as part of JSON serialization - exactly because it's rare that they satisfy our JSON requirements.
So instead we create a special DTO class which maps exactly how we need it for a particular endpoint. We convert our Entity to the DTO (and it will not include account
field) and then serialize DTO.
Jackson has a notion of a JsonView - it lets you map the same object differently depending on the view that you request. This way you can make account
field invisible to that particular endpoint.
As was already hinted in the other response - you can @JsonIgnore
the property or rid of its visibility or making it deserialize-only with WRITE_ONLY.
Jackson has "plugins" specific for Hibernate: jackson-datatype-hibernate. They allow to be configured to ignore lazy fields and not initialize them. In such case Jackson will serialize null (HibernateXModule.Feature).
This is probably the worst option of all because you really don't want to tie how you optimize your work with DB and your presentation layer.