This is what my SQL tables look like:
CREATE TABLE IF NOT EXISTS `test`.`Families` (
`id` INT NOT NULL AUTO_INCREMENT,
`mother_id` INT DEFAULT NULL ,
`father_id` INT DEFAULT NULL ,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `test`.`Parents` (
`id` INT NOT NULL AUTO_INCREMENT,
`first_name` VARCHAR(50) DEFAULT NULL,
`last_name` VARCHAR(50) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
And this is what my family entity looks like:
#Entity
#Table(name="Families")
public class Family implements Serializable {
#Id
#Column(name="id")
private String id;
#Column(name="mother_id")
private int mother;
#Column(name="father_id")
private int father;
}
Which is great and all, but I would really LOVE if I could do something like this (note I also have a Parent entity already defined):
#Entity
#Table(name="Families")
public class Family implements Serializable {
#Id
#Column(name="id")
private String id;
#OneToOne
#Column(name="mother_id")
private Parent mother;
#OneToOne
#Column(name="father_id")
private Parent father;
}
How could I go about making this happen?
Actually, Hibernate does everything for you.
You don't need to annotate columns with #Column which already have #OneToOne or other association annotations
If you want to use other than default foreign key(by default name consists of field + _id), you should use #JoinColumn annotation
#Entity
#Table(name="Families")
public class Family implements Serializable {
#Id
#Column(name="id")
private String id;
#OneToOne
#JoinColumn(name = "mother_idd")
private Parent mother;
#OneToOne
#JoinColumn(name = "father_idd")
private Parent father;
}
Related
I am having two entities having one-to-many & many-to-one relationship.
One side:
#Entity
#Table(name = "GAME_BLIND_STRUCTURE")
#Builder
#Getter
#Setter
public class GameBlindStructureEntity implements Serializable {
private static final long serialVersionUID = -7800120016594245121L;
#Id
#Column(name = "BLIND_ID")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long blindId;
#Column(name = "BLIND_STRUCTURE_NAME", unique = true)
private String blindStructureName;
#OneToMany(mappedBy = "gameBlindStructure")
private List<GameBlindStructureDetailsEntity> gameBlindStructureDetailsEntities;
}
Many-sided entity:
#Entity
#Table(name = "GAME_BLIND_STRUCTURE_DETAILS")
#Builder
#Getter
#Setter
public class GameBlindStructureDetailsEntity implements Serializable {
private static final long serialVersionUID = -7800120016594245121L;
#Id
#Column(name = "BLIND_DETAILS_ID")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long blindDetailsId;
#ManyToOne
#JoinColumn(name = "BLIND_ID")
private GameBlindStructureEntity gameBlindStructure;
#Column(name = "LEVEL")
private String level;
#Column(name = "SMALL_BLIND")
private Integer smallBlind;
#Column(name = "BIG_BLIND")
private Integer bigBlind;
#Column(name = "ANTE")
private Integer ante;
#Column(name = "TIME_BANK")
private String timeBank;
#Column(name = "MINUTES")
private Integer minutes;
}
In the service method, I am trying to persist these entities to database.
public BlindStructureResponseDto createBlindStructure(BlindStructureDto blindStructureDto) {
GameBlindStructureEntity gameBlindStructureEntity = GameBlindStructureEntity.builder()
.blindStructureName(blindStructureDto.getName())
.build();
List<BlindStructureDetailsDto> blindStructureDetailsDtos = blindStructureDto.getBlindStructureDetailsDtos();
List<GameBlindStructureDetailsEntity> gameBlindStructureDetailsEntities = new ArrayList<>();
for(BlindStructureDetailsDto blindStructureDetailsDto : blindStructureDetailsDtos) {
GameBlindStructureDetailsEntity gameBlindStructureDetailsEntity = mapper.convertToGameStructureDetailsEntity(blindStructureDetailsDto);
gameBlindStructureDetailsEntity.setGameBlindStructure(gameBlindStructureEntity);
gameBlindStructureDetailsEntities.add(gameBlindStructureDetailsEntity);
}
gameBlindStructureEntity.setGameBlindStructureDetailsEntities(gameBlindStructureDetailsEntities);
GameBlindStructureEntity savedEntity = blindStructureRepository.save(gameBlindStructureEntity);
BlindStructureResponseDto blindStructureResponseDto = BlindStructureResponseDto.builder()
.name(savedEntity.getBlindStructureName())
.blindId(savedEntity.getBlindId())
.build();
return blindStructureResponseDto;
}
Though the entity on one-side is getting persisted to the database, the many sided entity is not getting saved.
Here is the ddl script:
DROP TABLE IF EXISTS `GAME_BLIND_STRUCTURE`;
CREATE TABLE `GAME_BLIND_STRUCTURE`
( `BLIND_ID` INT AUTO_INCREMENT,
`BLIND_STRUCTURE_NAME` VARCHAR(255) NOT NULL,
PRIMARY KEY (`BLIND_ID`),
UNIQUE KEY `UNIQUE_BLIND_STRUCTURE_NAME` (`BLIND_STRUCTURE_NAME`)
) ENGINE=INNODB DEFAULT CHARSET=latin1;
DROP TABLE IF EXISTS `GAME_BLIND_STRUCTURE_DETAILS`;
CREATE TABLE `GAME_BLIND_STRUCTURE_DETAILS`
(`BLIND_DETAILS_ID` INT AUTO_INCREMENT,
`BLIND_ID` INT NOT NULL,
`LEVEL` VARCHAR(255) NOT NULL,
`SMALL_BLIND` INT NOT NULL,
`BIG_BLIND` INT NOT NULL,
`ANTE` INT NOT NULL,
`TIME_BANK`VARCHAR(255) NOT NULL,
`MINUTES` INT NOT NULL,
PRIMARY KEY(`BLIND_DETAILS_ID`),
CONSTRAINT `FK_BLIND_ID` FOREIGN KEY (`BLIND_ID`) REFERENCES `GAME_BLIND_STRUCTURE` (`BLIND_ID`)
)ENGINE=INNODB DEFAULT CHARSET=latin1;
You're missing CascadeType.ALL on your #OneToMany annotation, code should be as follows:
#OneToMany(mappedBy = "gameBlindStructure", cascade = CascadeType.ALL)
private List<GameBlindStructureDetailsEntity> gameBlindStructureDetailsEntities;
I have 2 tables Book and Author in a Many to Many Relationship using a candidate key table author_book which has primary keys of both author and Book.
I'm trying to get all books from a given author by AUTHOR_ID, maybe after if it works I'll try to do search by name
create table author_book(
`AUTHOR_ID` INT,
`BOOK_ID` INT
);
`
create table author(
`AUTHOR_ID` int auto_increment,
`FIRST_NAME` varchar(255),
`LAST_NAME` varchar(255),
`EMAIL` varchar(30),
`CONTACT_NO` VARCHAR(10),
primary key(AUTHOR_ID)
);
create table book(
`BOOK_ID` int auto_increment,
`TITLE` varchar(255),
`SUBJECT` varchar(255),
`PUBLISHED_YEAR` int,
`ISBN` varchar(30),
`QUANTITY` int,
`SHELF_DETAILS` varchar(255),
`PUBLISHER_ID` int,
`BOOK_COST` INT,
primary key(BOOK_ID)
);
I decided I'll create AUTHOR_NAME using CONCAT
I tried this query for search by author_id
#Query("select b from Books b where b.bookId in (select a.bookId from author_book a where a.author_id = :Id)")
but I'm getting error that author_book is not mapped so do I need to create another entity for this class to perform any operations b/w these 2 class? I'm also not sure if nested queries work in JPQL, this was basically a hunch.
My Books Entity
#Entity
#Table(name = "book")
public class Books implements Serializable{
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="BOOK_ID")
private int bookId;
#Column(name="TITLE")
private String title;
#Column(name="SUBJECT")
private String subject;
#Column(name="PUBLISHED_YEAR")
private int publishedYear;
#Column(name="ISBN")
private String isbn;
#Column(name="QUANTITY")
private int quantity;
#Column(name="SHELF_DETAILS")
private String shelfDetails;
#Column(name="BOOK_COST")
private int bookCost;
#JsonIgnore
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable(name = "author_book",
joinColumns = { #JoinColumn(name = "BOOK_ID") },
inverseJoinColumns = { #JoinColumn(name = "AUTHOR_ID") })
private Set<Authors> authors = new HashSet<Authors>();
#JsonIgnore
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name="PUBLISHER_ID")
private Publishers publisher;
// getters and setters
}
My Authors Entity
#Entity
#Table(name="author")
public class Authors {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="AUTHOR_ID")
private int authorId;
#Column(name="FIRST_NAME")
private String firstName;
#Column(name="LAST_NAME")
private String lastName;
#Column(name="EMAIL")
private String email;
#Column(name="CONTACT_NO")
private String contactNo;
#JsonIgnore
#ManyToMany(fetch = FetchType.LAZY, mappedBy = "authors")
private Set<Books> books = new HashSet<Books>();
// Getters and setters
}
You should add mappedBy things in Authors Entity.
#ManyToMany(mappedBy="authors", fetch=FetchType.LAZY)
private Set<Books> books = new HashSet<Books>();
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.Tue Oct 10 17:11:14 IST 2018 There was an unexpected error (type=Internal Server Error, status=500). could not execute statement; SQL [n/a]; nested exception is org.
hibernate.exception.SQLGrammarException: could not execute statement.
STS Error:
Before changing the code
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolation
Exception
: Cannot add or update a child row: a foreign key constraint fails
(workdemo.officeinfo, CONSTRAINT idFOREIGN KEY (id) REFERENCES mytable
(id))
After implementing joincolumn
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'entityManagerFactory' defined in class path
resource [org/springframework/boot/autoconfigure/orm/jpa/
HibernateJpaConfiguration.class]: Invocation of init method failed;
nested exception is org.hibernate.AnnotationException: No identifier
specified for entity:com.infidata.modal.MyTable
POJO( value with getters and setters,also
generated value)
Office.java
package com.infidata.modal;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
#Entity
#Table(name="officeinfo")
public class Office {
#Id
private int sno;
private String batchno;
#ManyToOne
#JoinColumn(name = "id" )
private MyTable myTable;
private String fees;
private String reciptno;
private String trainer;
public Office() {
}
public int getSno() {
return sno;
}
public void setSno(int sno) {
this.sno = sno;
}
public String getBatchno() {
return batchno;
}
public void setBatchno(String batchno) {
this.batchno = batchno;
}
public String getFees() {
return fees;
}
public void setFees(String fees) {
this.fees = fees;
}
public String getReciptno() {
return reciptno;
}
public void setReciptno(String reciptno) {
this.reciptno = reciptno;
}
public String getTrainer() {
return trainer;
}
public void setTrainer(String trainer) {
this.trainer = trainer;
}
public Office(String batchno,String fees, String reciptno,String trainer) {
super();
this.batchno = batchno;
this.fees = fees;
this.reciptno = reciptno;
this.trainer=trainer;
}
#Override
public String toString() {
return "Office [sno=" + sno + ", batchno=" + batchno + ",fees=" + fees
+ ", reciptno=" + reciptno + ",trainer=" + trainer + "]";
}
}
MyTable.java
package com.infidata.modal;
#Entity
public class MyTable {
}
Database(name of database is workdemo)
User table(Table name: mytable)
CREATE TABLE `mytable`
( `id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(45) NOT NULL,
`mobile` varchar(10) NOT NULL,
`email` varchar(45) NOT NULL,
`college` varchar(45) NOT NULL,
`branch` varchar(45) NOT NULL,
`semester` varchar(45) NOT NULL,
`address` varchar(105) NOT NULL,
`internship` varchar(45) NOT NULL,
`batch` varchar(45) NOT NULL,
`startdate` varchar(45) NOT NULL,
`enddate` varchar(45) NOT NULL,
PRIMARY KEY (`id`)
)
ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_0900_ai_ci
Office table(Table name:office)
CREATE TABLE `office`
(`sno` int(11) NOT NULL AUTO_INCREMENT,
`batchno` varchar(45) NOT NULL,
`id` int(11) NOT NULL,
`fees` varchar(45) NOT NULL,
`reciptno` varchar(45) NOT NULL,
PRIMARY KEY (`sno`),
KEY `id_idx` (`id`),
CONSTRAINT `id` FOREIGN KEY (`id`) REFERENCES `mytable` (`id`)
)
ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
The id(foreign key) in office table should be autoincremented with reference to student id column attribute
The problem is how you defined the entity class :
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
When you use JPA, you must specify the target entity of the relationship, not the field from database.
Your definition just tells the hibernate to generate an int value which will not correspond to a real entity.
It should be something like this:
#ManyToOne
#JoinColumn(name = "id" )
private User user;
Your office object will be
#Entity
#Table(name = "officeinfo")
public class Office {
#Id
private int sno;
private String batchno;
#ManyToOne
#JoinColumn(name = "id")
private User user;
private String fees;
private String reciptno;
private String trainer;
// getters and setters;
}
Please make sure that #Id is only on sno and you don't have on another fields, otherwise it will fail with composite key exception. Please remove id from your object, it is the foreign key to User and it is handled by:
#ManyToOne
#JoinColumn(name = "id")
private User user;
I am a bit disconcerted with this and I am asking for help just in order to understand what is happening.
So, I have this table (DDL):
CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`firstname` varchar(45) NOT NULL,
`lastname` varchar(45) NOT NULL,
`email` varchar(60) NOT NULL,
`password` varchar(100) NOT NULL,
`enabled` tinyint(1) NOT NULL,
`created_at` datetime DEFAULT NULL,
`image_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `email_UNIQUE` (`email`),
KEY `FK17herqt2to4hyl5q5r5ogbxk9` (`image_id`),
CONSTRAINT `FK17herqt2to4hyl5q5r5ogbxk9` FOREIGN KEY (`image_id`) REFERENCES `images` (`id`),
CONSTRAINT `fk_users_images1` FOREIGN KEY (`image_id`) REFERENCES `images` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1
And my entity:
#Entity
#Table(name = "users")
public class User implements Serializable {
private static final long serialVersionUID = 6304869652591140818L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id", updatable = false, nullable = false)
private Long id;
#Column(name = "firstname")
private String firstname;
#Column(name = "lastname")
private String lastname;
#Column(name = "email")
private String email;
#Column(name = "password")
#Transient
private String password;
#Column(name = "enabled")
private int enabled;
#Column(name = "created_at")
private LocalDateTime createdAt;
#ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinTable(name = "users_has_roles",
joinColumns = #JoinColumn(name = "user_id"),
inverseJoinColumns = #JoinColumn(name = "role_id"))
private Set<Role> roles;
#MapsId
#OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private Image image;
// Setters and Getters
}
I am trying to persist a new User with this code:
#PersistenceContext
private EntityManager em;
#Transactional
public void createUser(NewUserDto newUser) {
User user = new User();
user.setFirstname(newUser.getFirstname());
user.setLastname(newUser.getLastname());
user.setEmail(newUser.getEmail());
user.setEnabled(ENABLED);
user.setPassword(bCryptPasswordEncoder.encode(newUser.getPassword()));
Image userImage = imageService.getImageById(1L);
user.setProfileImage(userImage);
Set<Role> roles = new HashSet<Role>();
Role role = roleRepository.findByName(newUser.getRole());
roles.add(role);
user.setRoles(roles);
if (user.getId() == null) {
em.persist(user);
em.flush();
} else {
em.merge(user);
}
}
The thing is that when I debug I see that always generates id=1 for the new user.
But in the database, I see all correct.
And when i search for all users i get the following:
public List<User> getAll() {
return userRepository.findAll();
}
The same JPDA ObjectReference.
Any help will be welcomed.
Thanks.
(Apologies for not having enough reputation to leave a comment)
I do not understand your question clearly. Anyway i will try to explain based on what I think is your problem.
By default, the starting value for AUTO_INCREMENT is 1, and it will
increment by 1 for each new record. So that behavior is expected.
If you want it to start with a value that is not 1, then you must use
a GenerationType.SEQUENCE with appropriate changes.
Image1: You have mentioned that the values are getting entered into
the database correctly and this shows that the Id values are being
generated correctly
Image2: users is a Javascript array. Index values of javascript
arrays always start from zero. That is just the index value and NOT
the id value. Similarly, the id mentioned on the right is the
javascript's internal object id and not the actual Id of your user.
To see the real id of the user, expand the user at position 0.
If this does not answer your questions, kindly elaborate your question and what exactly is the error or issue.
The problem stems from a misunderstanding where Hibernate's fallback for GenerationType.AUTO is GenerationType.SEQUENCE, while what most people want is GenerationType.IDENTITY, so you can use the id the database assigns you. simply change the strategy to IDENTITY and your problem is solved.
I'm newb to JPA. I'm having trouble with defining OneToOne bidirectional flow on my classes.
UserInfo.java:
#Entity
#Table(name="UserInfo")
public class UserInfo {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer idUserInfo;
private String firstName;
private String lastName;
#OneToOne(mappedBy="UserInfo")
private LoginInfo loginInfo;
LoginInfo.java:
#Entity
#Table(name="LoginInfo")
public class LoginInfo {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer idLoginInfo;
#Column(name="emailId")
private String emailId;
//bidirectional one to one association to UserInfo
#OneToOne
#JoinColumn(name="emailId", referencedColumnName="loginInfo")
private UserInfo userInfo;
private String sessionId;
private String password;
Here's sql to create those tables:
CREATE TABLE `LoginInfo` (
`emailId` varchar(45) NOT NULL,
`idLoginInfo` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`idLoginInfo`),
UNIQUE KEY `emailId_UNIQUE` (`emailId`),
UNIQUE KEY `id_UNIQUE` (`idLoginInfo`)
);
DROP TABLE IF EXISTS `UserInfo`;
CREATE TABLE `UserInfo` (
`idUserInfo` int(11) NOT NULL AUTO_INCREMENT,
`firstName` varchar(45) NOT NULL,
`lastName` varchar(45) NOT NULL,
`loginInfo` varchar(45) NOT NULL,
PRIMARY KEY (`idUserInfo`),
UNIQUE KEY `idUserInfo_UNIQUE` (`idUserInfo`),
UNIQUE KEY `loginInfo_UNIQUE` (`loginInfo`),
CONSTRAINT `loginInfo` FOREIGN KEY (`loginInfo`) REFERENCES `LoginInfo` (`emailId`) ON DELETE CASCADE ON UPDATE CASCADE
);
When I start the Tomcat server, I'm getting the follow exception on ContextInitialization.
Caused by: org.hibernate.MappingException: Unable to find column with logical name: loginInfo in org.hibernate.mapping.Table(UserInfo) and its related supertables and secondary tables
But the column do exist on the UserInfo table. Can somebody please help me if the mapping is right?
Thanks
Invalid association : #JoinColumn(name="emailId", referencedColumnName="loginInfo")
#Entity
#Table(name="UserInfo")
public class UserInfo {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer idUserInfo;
private String firstName;
private String lastName;
#OneToOne(mappedBy = "userInfo", cascade = CascadeType.ALL)
private LoginInfo loginInfo;
#Entity
#Table(name="LoginInfo")
public class LoginInfo {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer idLoginInfo;
#Column(name="emailId")
private String emailId;
//bidirectional one to one association to UserInfo
#OneToOne
#PrimaryKeyJoinColumn
private UserInfo userInfo;
private String sessionId;
private String password;
After reading about OneToOne mapping, annotations and some trial & error, I was able to use the LoginInfo and UserInfo tables successfully. In my question above, it has some invalid mappings. The requirement was that UserInfo be the owner entity and LoginInfo as the child entity. So as suggested by ashokhein, I used PrimaryKeyJoinColumn annotation. This is how my tables look like now.
CREATE TABLE `login_info` (
`user_info_id` bigint(100) NOT NULL,
`email_id` varchar(45) NOT NULL,
PRIMARY KEY (`user_info_id`),
UNIQUE KEY `email_id_UNIQUE` (`email_id`),
UNIQUE KEY `user_info_id_UNIQUE` (`user_info_id`),
CONSTRAINT `FK_login_info_user_info` FOREIGN KEY (`user_info_id`) REFERENCES `user_info` (`user_info_id`) ON DELETE CASCADE ON UPDATE CASCADE);
CREATE TABLE `user_info` (
`user_info_id` bigint(100) NOT NULL AUTO_INCREMENT,
`first_name` varchar(50) DEFAULT NULL,
`last_name` varchar(50) DEFAULT NULL,
PRIMARY KEY (`user_info_id`),
UNIQUE KEY `user_info_id_UNIQUE` (`user_info_id`));
This is how my classes look like:
UserInfo:
#Entity
#Table(name = "user_info")
public class UserInfo {
#Id
#Column(name = "user_info_id")
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer userId;
#Column(name = "first_name")
private String firstName;
#Column(name = "last_name")
private String lastName;
#OneToOne(cascade = CascadeType.ALL)
#PrimaryKeyJoinColumn
private LoginInfo loginInfo;
//Getters and setters
LoginInfo:
#Entity
#Table(name = "login_info")
public class LoginInfo {
#Id
#Column(name = "user_info_id")
#GeneratedValue(generator = "generator")
#GenericGenerator(name = "generator", strategy = "foreign", parameters = #Parameter(name = "property", value = "userInfo"))
private Integer id;
#OneToOne
#PrimaryKeyJoinColumn
private UserInfo userInfo;
#Column(name = "email_id")
private String emailId;
//Getters and setters
And this is how I create and save the entities to the table:
UserInfo userInfo = new UserInfo();
userInfo.setFirstName(registerUserRequest.getFirstName());
userInfo.setLastName(registerUserRequest.getLastName());
LoginInfo loginInfo = userInfo.getLoginInfo();
if(loginInfo == null) {
loginInfo = new LoginInfo();
}
loginInfo.setEmailId(registerUserRequest.getEmailId());
loginInfo.setUserInfo(userInfo);
userInfo.setLoginInfo(loginInfo);
if(userService.create(userInfo)) {
logger.debug("User created successfully");
} else {
throw new UserAlreadyExistException();
}
During the course of getting to this solution, I encountered bunch of hibernate exceptions and issues. Here's some(if it helps someone)
Error: identifier of an instance of was altered from 14 to 14
Solution: The primary key on the Entity classes where different types initially. The column user_info_id was declared as Integer in UserInfo and long in LoginInfo.
Error: attempted to assign id from null one-to-one property
Solution: While creating the UserInfo object, I did "userInfo.setLoginInfo(loginInfo)" but did not set "loginInfo.setUserInfo(userInfo)". After fixing that, it was fine.
Note: If you see a better way to do the same, please do comment here and let me know. Thanks in advance.