Many to One Relationship returns NULL List of Child Object - spring-boot

I have 2 classes. USER class & ORDER class.
Order class has User object with #ManyToOne relationship.
When the RestController retrieves the Order object post insertion of Order object using #PostMapping,it returns null value for nested User object
Rest Controller
#RestController
public class OrderController {
#PersistenceContext
EntityManager entityManager;
#Transactional
#PostMapping(value = "api/v1/create/order")
public Order createOrder(#RequestBody Order order){
entityManager.persist(order);
return order;
}
}
Order class
#Entity
#Table(name = "booking_order")
public class Order {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
Integer orderID;
#Column
String transactionAmount;
#Column
#CreationTimestamp
#Temporal(TemporalType.TIMESTAMP)
Date bookingTimestamp;
#ManyToOne
User user;
public Order(){}
public Integer getOrderID() {
return orderID;
}
public void setOrderID(Integer orderID) {
this.orderID = orderID;
}
public String getTransactionAmount() {
return transactionAmount;
}
public void setTransactionAmount(String transactionAmount) {
this.transactionAmount = transactionAmount;
}
public Date getBookingTimestamp() {
return bookingTimestamp;
}
public void setBookingTimestamp(Date bookingTimestamp) {
this.bookingTimestamp = bookingTimestamp;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
User Class
#Entity
#Table(name = "user")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
Integer id;
#Column(unique = true)
String username;
#Column
String password;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
Input JSON
{
"transactionAmount" : "100.50",
"user":{
"id":1
}
}
Order Response
{
"orderID": 1,
"transactionAmount": "100.50",
"bookingTimestamp": "2019-05-15T20:44:43.234+0000",
"user": {
"id": 1,
"username": null,
"password": null
}
}

Related

How should I Map foreign keys in entity classes to model class (pojo) objects

Model Class for User:
#Component
public class UserModel {
private Integer userId;
private Integer roleId;
private String firstName;
private String email;
private String password;
public Integer getUserId() {
return userId;
}
public Integer getRoleId() {
return roleId;
}
public String getFirstName() {
return firstName;
}
public String getEmail() {
return email;
}
public String getPassword() {
return password;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public void setRoleId(Integer roleId) {
this.roleId = roleId;
}
public void setName(String firstName) {
this.firstName = firstName;
}
public void setEmail(String email) {
this.email = email;
}
public void setPassword(String password) {
this.password = password;
}
}
Model Class for Role of the User:
#Component
public class RolesModel {
private Integer roleId;
private String roleName;
public Integer getRoleId() {
return roleId;
}
public void setRoleId(Integer roleId) {
this.roleId = roleId;
}
public String getRoleName() {
return roleName;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
}
Entity Class for User:
#Entity
#Table(name = "userBloodBank")
public class User {
#Id
#GeneratedValue (strategy = GenerationType.AUTO)
private Integer userId;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name="roleId")
private Roles roles;
#NotNull
#Column
#Pattern(regexp="[A-Z][a-zA-Z]*",message="Only enter words starting with captital letter")
private String firstName;
#NotNull
#Column
#Email
#Pattern(regexp = "^[a-zA-Z0-9+_.-]+#[a-zA-Z0-9.-]+$", message = "Enter a proper email ID")
private String email;
#NotNull
#Column
#Pattern(regexp= "^(?=.*[0-9])"
+ "(?=.*[a-z])(?=.*[A-Z])"
+ "(?=.*[##$%^&+=])"
+ "(?=\\S+$).{8,20}$", message="Enter minimum 8 characters and maximum 20 characters")
private String password;
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public Roles getRoles() {
return roles;
}
public void setRoles(Roles roles) {
this.roles = roles;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
Entity Class for Role:
#Entity
#Table(name="Roles")
public class Roles {
#Id
#GeneratedValue (strategy = GenerationType.AUTO)
private Integer roleId;
#NotNull
#Column
#Pattern(regexp="(Recipient|Donor|BloodBankAdmin|Admin)", message = "Choose among Recipient|Donor|BloodBankAdmin|Admin")
private String roleName;
public Integer getRoleId() {
return roleId;
}
public void setRoleId(Integer roleId) {
this.roleId = roleId;
}
public String getRoleName() {
return roleName;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
}
In the above case Role Id has oneToOne relationship and how will I map this to model object of role and user? Help me with the code to create the function "convertModelToEntity()" and "convertEntityToModel".
You can add below code in your User-entity class to map entity with Model.
public static UserModel convertEntityToModel(User user) {
UserModel userModel = new UserModel();
userModel.setUserId(user.getUserId());
userModel.setRoleId(user.getRoles().getRoleId());
userModel.setFirstName(user.getFirstName());
userModel.setEmail(user.getEmail());
userModel.setPassword(user.getPassword());
return userModel;
}
This will return User-model.
I think you should add the Roles-model(or list of Roles-model) in User Model.

Null value in primary key of hibernate entity

I faced with problem of null value in PK.
Here's an entity:
#Entity
#Table(name="space")
public class Space implements Serializable {
#Id
#GeneratedValue
#Column(nullable = false, unique = true)
private Long id;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name="user_id")
private UserAccount user;
private String name;
private String description;
private Date createdTime;
private Date modifiedTime;
#OneToMany(mappedBy="space")
private Set<SpaceAccess> spaceAccesses = new HashSet<>();
public Set<SpaceAccess> getSpaceAccesses() {
return spaceAccesses;
}
public void setSpaceAccesses(Set<SpaceAccess> spaceAccesses) {
this.spaceAccesses = spaceAccesses;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Space() {}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public UserAccount getUser() {
return user;
}
public void setUser(UserAccount user) {
this.user = user;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Date getCreatedTime() {
return createdTime;
}
public void setCreatedTime(Date createdTime) {
this.createdTime = createdTime;
}
public Date getModifiedTime() {
return modifiedTime;
}
public void setModifiedTime(Date modifiedTime) {
this.modifiedTime = modifiedTime;
}
}
I wrote strategy to generate PK properly but I always get Null in id field when I create new instance of the Space:
Space space = new Space();
Here's content of the object:
What i should do to generate id of instance properly using hibernate/spring mechanisms?
application.properties:
spring.datasource.url="some_url"
spring.datasource.username=name
spring.datasource.password=password
spring.jpa.generate-ddl=true
P.S. I use spring-boot-starter-data-jpa with version: 2.3.4.RELEASE.
Use:
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}

Spring Not Mapping Composite Key Entity To Database

I have two entities User and Focus for which I must store a ranking such that a User can have a ranking for many Focus', and a Focus may have many users. To handle this I've followed https://www.baeldung.com/jpa-many-to-many part 3 whereby I have the 2 following classes:
#Entity(name = "UserBaseRatings")
public class Rating {
#EmbeddedId
RatingKey id;
#ManyToOne
#MapsId("userID")
#JoinColumn(name="userID")
private User user;
#ManyToOne
#MapsId("focusID")
#JoinColumn(name="focusID")
private Focus focus;
private BigDecimal baseRating;
protected Rating(){}
public Rating(User user, Focus focus, BigDecimal baseRating) {
this.user = user;
this.focus = focus;
this.baseRating = baseRating;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Focus getFocus() {
return focus;
}
public void setFocus(Focus focus) {
this.focus = focus;
}
public BigDecimal getBaseRating() {
return baseRating;
}
public void setBaseRating(BigDecimal baseRating) {
this.baseRating = baseRating;
}
}
and
#Embeddable
public class RatingKey implements Serializable {
#Column(name="userID")
private Long userID;
#Column(name="focusID")
private Long focusID;
protected RatingKey(){}
public RatingKey(Long userID, Long focusID) {
this.userID = userID;
this.focusID = focusID;
}
public Long getUserID() {
return userID;
}
public void setUserID(Long userID) {
this.userID = userID;
}
public Long getFocusID() {
return focusID;
}
public void setFocusID(Long focusID) {
this.focusID = focusID;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
RatingKey ratingKey = (RatingKey) o;
return Objects.equals(userID, ratingKey.userID) &&
Objects.equals(focusID, ratingKey.focusID);
}
#Override
public int hashCode() {
return Objects.hash(userID, focusID);
}
}
The table for UserBaseRatings has a default value of 1 for baseRating such that if a user does not have a rating on the current focus their rating should be 1. I'm running into a problem where if the user hasn't made a rating then the set of Rating's is empty instead of having a rating of 1 for each focus that exists.
User:
public class User {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long userID;
#Column(name = "userHashedPassword")
private String password;
#Column(name = "userName")
private String userName;
#Column(name = "userEmail")
private String email;
//probably being reset
#Transient
private List<String> groups = new LinkedList<>();
#ManyToMany
#JoinTable(name = "UserRoles",
joinColumns = #JoinColumn(
name = "userID"),
inverseJoinColumns = #JoinColumn(
name = "roleID"))
private Set<Role> roles = new HashSet<>();
#OneToMany(mappedBy = "user")
private Set<Rating> ratings;
protected User(){}
public User(String userHashedPassword, String userName, String email, Set<Role> roles){
this.password = userHashedPassword;
this.userName = userName;
this.email = email;
this.roles = roles;
}
public Long getUserId() {
return userID;
}
public void setId(Long userID) {
this.userID = userID;
}
public String getPassword(){
return password;
}
public void setPassword(String password){
this.password = password;
}
public String getUsername() {
return userName;
}
public void setUsername(String name) {
this.userName = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Set<Role> getRoles() {
return roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
public Set<Rating> getRatings() {
return ratings;
}
public void setRatings(Set<Rating> ratings) {
this.ratings = ratings;
}
}
Focus:
#Entity
public class Focus {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private Long focusID;
private String focusCategory;
private String focusName;
private String focusExplanation;
#OneToMany(mappedBy = "focus")
Set<Rating> ratings;
//image
protected Focus(){}
public Focus(String focusCategory, String focusName, String focusExplanation, Set<Rating> ratings){
this.focusCategory = focusCategory;
this.focusName = focusName;
this.focusExplanation = focusExplanation;
this.ratings = ratings;
}
public Long getFocusId() {
return focusID;
}
public void setFocusId(Long focusID) {
this.focusID = focusID;
}
public String getFocusCategory() {
return focusCategory;
}
public void setFocusCategory(String focusCategory) {
this.focusCategory = focusCategory;
}
public String getFocusName() {
return focusName;
}
public void setFocusName(String focusName) {
this.focusName = focusName;
}
public String getFocusExplanation() {
return focusExplanation;
}
public void setFocusExplanation(String focusExplanation) {
this.focusExplanation = focusExplanation;
}
public Set<Rating> getRatings() {
return ratings;
}
public void setRatings(Set<Rating> ratings) {
this.ratings = ratings;
}
}
What am I missing that will allow a User's Ratings to be populated with the default value for each Focus that exists in the database?
Edit: Added #PrePersist and #PreUpdate to the Rating entity:
#Entity(name = "UserBaseRatings")
public class Rating {
#EmbeddedId
RatingKey id;
#ManyToOne
#MapsId("userID")
#JoinColumn(name="userID")
private User user;
#ManyToOne
#MapsId("focusID")
#JoinColumn(name="focusID")
private Focus focus;
private BigDecimal baseRating;
protected Rating(){}
public Rating(User user, Focus focus, BigDecimal baseRating) {
this.user = user;
this.focus = focus;
this.baseRating = baseRating;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Focus getFocus() {
return focus;
}
public void setFocus(Focus focus) {
this.focus = focus;
}
public BigDecimal getBaseRating() {
return baseRating;
}
public void setBaseRating(BigDecimal baseRating) {
this.baseRating = baseRating;
}
#PrePersist
public void prePersist() {
if(baseRating == null) {
baseRating = BigDecimal.ONE;
}
}
#PreUpdate
public void preUpdate() {
if(baseRating == null) {
baseRating = BigDecimal.ONE;
}
}
}
Changing spring.jpa.hibernate.ddl-auto= from none to update also made no difference.
If you use ORM all default values have to be explicitly declared. It can be done this way
#Entity(name = "UserBaseRatings")
public class Rating {
// ...
private BigDecimal baseRating = BigDecimal.ONE;
// ...
}
or use #PrePersist and #PreUpdate
#Entity(name = "UserBaseRatings")
public class Rating {
// ...
private BigDecimal baseRating;
// ...
#PrePersist
public void prePersist() {
if(baseRating == null) {
baseRating = BigDecimal.ONE;
}
}
#PreUpdate
public void preUpdate() {
if(baseRating == null) {
baseRating = BigDecimal.ONE;
}
}
}

could not resolve property: product_id of: Comment

Getting an error on server startup a query that finds all comments posted by a user about a specific product.
Caused by: java.lang.IllegalArgumentException: org.hibernate.QueryException: could not resolve property: product_id of: haughton.dvdstore.model.Comment [select c from haughton.dvdstore.model.Comment c where c.product_id = :id]
Repo class
#Repository
public interface CommentDao extends CrudRepository<Comment,Long> {
#Query("select c from Comment c where c.product_id = :id")
List<Comment> allCommentsByProductId(#Param("id") Long id);
}
Comment class
#Entity
public class Comment {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#ManyToOne
#JoinColumn(name = "product_id")
private Product product;
#ManyToOne
#JoinColumn(name = "user_id")
private User user;
private String text;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Product getProduct() {
return product;
}
public void setProduct(Product product) {
this.product = product;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
My product class
#Entity
public class Product {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
private String description;
private int quantityInStock;
Date date;
private double price;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public int getQuantityInStock() {
return quantityInStock;
}
public void setQuantityInStock(int quantityInStock) {
this.quantityInStock = quantityInStock;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
User class
#Entity
public class User implements UserDetails {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(unique = true)
#Size(min = 8, max = 20)
private String username;
#Column(length = 100)
private String password;
#Column(nullable = false)
private boolean enabled;
#OneToOne
#JoinColumn(name = "role_id")
private Role role;
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
List<GrantedAuthority> authorities = new ArrayList<>();
authorities.add(new SimpleGrantedAuthority(role.getName()));
return authorities;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
#Override
public String getPassword() {
return password;
}
#Override
public String getUsername() {
return username;
}
#Override
public boolean isAccountNonExpired() {
return true;
}
#Override
public boolean isAccountNonLocked() {
return true;
}
#Override
public boolean isCredentialsNonExpired() {
return true;
}
#Override
public boolean isEnabled() {
return enabled;
}
public static PasswordEncoder getPasswordEncoder() {
return PASSWORD_ENCODER;
}
}
It should have been #Query("select c from Comment c where c.product.id = :id")

[org.hibernate.mapping.Column(authorities)]

I have follow Hibernate error:
"Could not determine type for: java.util.List, at table: user, for columns: [org.hibernate.mapping.Column(authorities)]"
What can cause a problem?
Also, is it possible use it without model role, and set return getAuthority role "USER" by default?
User model:
#Entity
#Table(name = "user")
public class User implements UserDetails {
private int id;
private String username;
private String password;
private List<Role> roles;
#Id
#GeneratedValue
#Column(name = "id")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
#Basic
#Column(name = "username")
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
#Basic
#Column(name = "password")
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
#Override
public String getUsername() {
return this.username;
}
#Override
public boolean isAccountNonExpired() {
return true;
}
#Override
public boolean isAccountNonLocked() {
return true;
}
#Override
public boolean isCredentialsNonExpired() {
return true;
}
#Override
public boolean isEnabled() {
return true;
}
#Override
public List<Role> getAuthorities() {
return this.roles;
}
#OneToMany(mappedBy = "user")
public List<Role> getRoles() {
return this.roles;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
}
Role model:
#Entity
#Table(name = "role")
public class Role implements GrantedAuthority {
private int id;
private User user;
private String role;
public Role() {
}
public Role(String role){
this.role = role;
}
#Id
#GeneratedValue
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
#ManyToOne
#JoinColumn(name="user_id")
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
#Override
public String getAuthority() {
return this.role;
}
#Basic
#Column(name="role")
public String getRole(){
return this.role;
}
public void setRole(String role){
this.role = role;
}
}
I found solution myself. I set #Transient annotation to all method, which i don't want that it shouldn't be column in table.
You must replace all annotations for the attributes not to the getter methods.

Resources