Unable to insert data using hibernate one to one mapping - java

I have two tables:
ptUSER(userID, name)
ptProteinData(userID, total, goal)
I tried to implement this using Hibernate one to one relationship.
The implementation of those 2 tables are the following:
Implementation of ptUser table (User.java):
#Entity
#Table(name = "ptuser")
public class User implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "userID", unique = true, nullable = false)
int userID;
#Column(name = "name", unique = true, nullable = false, length = 45)
String name;
#OneToOne(fetch = FetchType.LAZY, mappedBy = "ptuser", cascade = CascadeType.ALL)
ProteinData proteinData;
// getters and setters
}
Implementation of ptProteinData table (ProteinData.java):
#Entity
#Table(name = "ptproteindata")
public class ProteinData {
#Id
#GeneratedValue(generator = "generator")
#GenericGenerator(name = "generator", strategy = "foreign", parameters = #Parameter(name = "property", value = "ptuser"))
int userID;
int total;
int goal;
#OneToOne(fetch = FetchType.LAZY)
#PrimaryKeyJoinColumn
User user;
//getter & setter
}
DAO layer implementation is like the following:
public class UserDAO {
public void addUserWithProteinData(String name, int goal, int total) {
Session session = HibernateUtilities.getSessionFactory().openSession();
session.beginTransaction();
User user = new User();
user.setName(name);
ProteinData proteinData = new ProteinData();
proteinData.setGoal(goal);
proteinData.setTotal(total);
user.setProteinData(proteinData);
proteinData.setUser(user);
session.saveOrUpdate(user);
session.getTransaction().commit();
session.close();
}
}
I tried to insert data using the following code:
UserDAO uDAO = new UserDAO();
uDAO.addUserWithProteinData("abc", 100, 10);
But I am unable to insert data using the above codes. Can you tell me where I am doing mistake. When I tried to execute this I am getting the following error:
Exception in thread "main"
java.lang.NullPointerException
at mydomain.UserDAO.addUserWithProteinData(UserDAO.java:43)
at mydomain.UserDAO.main(UserDAO.java:65)

Add the first line to your code, because you need to save proteinData first and then set in user object. Finally, you can save user.
session.saveOrUpdate(proteinData); // you need to save 'proteinData' first
user.setProteinData(proteinData);
proteinData.setUser(user);
session.saveOrUpdate(user);
Also amend these
// On User Class
#Entity
#Table(name = "ptuser")
public class User implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "userID")
int userID;
#Column(name = "name", unique = true, nullable = false, length = 45)
String name;
#OneToOne(fetch = FetchType.LAZY, mappedBy = "ptuser", cascade = CascadeType.ALL)
#PrimaryKeyJoinColumn
ProteinData proteinData;
}
// On ProteinData
#Entity
#Table(name = "ptproteindata")
public class ProteinData {
#Id
#GeneratedValue(generator = "generator")
#GenericGenerator(name = "generator", strategy = "foreign", parameters = #Parameter(name = "property", value = "ptuser"))
int userID;
int total;
int goal;
#OneToOne(fetch = FetchType.LAZY, mappedBy="ProteinData")
#PrimaryKeyJoinColumn
User user;
}

Add
(optional=false)
#JoinColumn(name="userID", unique=true, nullable=false, updatable=false)
What is the primary key of the second table ProteinData

Related

How to use Hibernate Check constraint in this case?

I want to use check constraint to verify if there are more students in the subject more than vacancies. These are the entities:
SubjectOffer
#Entity
#SequenceGenerator(name = "SUBJECT_OFFER_SEQ", sequenceName = "SUBJECT_OFFER_SEQ")
#Table(name = "SUBJECT_OFFER", uniqueConstraints = {
#UniqueConstraint(name = "UQ_SUBJECT_OFFER_COURSE_SUBJECT_SEMESTER_CLASS", columnNames = {"COURSE_ID", "SUBJECT_ID", "SEMESTER", "CLASS_NUMBER"})})
#Check(constraints = "COUNT(STUDENT_SUBJECT_ID) <= VACANCIES")
public class SubjectOffer {
#Id
#GeneratedValue(generator = "SUBJECT_OFFER_SEQ")
#Column(name = "SUBJECT_OFFER_ID", nullable = false)
private Long id;
#OneToMany(fetch = FetchType.LAZY, orphanRemoval = true, cascade = CascadeType.ALL)
#JoinColumn(name = "STUDENT_SUBJECT_ID")
private Set<StudentSubject> studentSubjects = new HashSet<>();
//other attributes
#Column(name = "VACANCIES", nullable = false)
private int vacancies;
}
StudentSubject
#Entity
#Table(name = "STUDENT_SUBJECT")
public class StudentSubject {
#EmbeddedId
private StudentSubjectId id = new StudentSubjectId();
#MapsId("studentId")
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "STUDENT_ID", nullable = false)
private Student student;
#MapsId("subjectOfferId")
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "SUBJECT_OFFER_ID", nullable = false)
private SubjectOffer subjectOffer;
#Column(name = "SEMESTER", nullable = false)
private int semester;
#Column(name = "GRADE")
private BigDecimal grade;
}
I also tried column definition in Set #JoinColumn but it didn't work
SQL check constraints only work on a single table. What you want is a so called SQL assertion constraint, but no database implements that. The best you can do is to pre-create rows for the amount of vacancies and just assign students to these rows without ever creating more rows. This way, you can make sure that you only assign as many students as there are vacancies, given that you use optimistic/pessimistic locking when assigning a student.

Got java "stackoverflow" when join two tables

I have two java entity classes :
#Table(name = "user")
public class UserEntity
{
#Id
#Column(name = "id", unique = true, nullable = false)
private Long id;
#OneToOne(cascade = CascadeType.PERSIST, fetch = FetchType.EAGER)
#JoinColumn(name = "opportunity_id")
private OpportunityEntity opportunity;
}
and
#Table(name = "opportunity")
public class OpportunityEntity
{
#Id
#Column(name = "id", unique = true, nullable = false)
private Long id;
#OneToMany
#JoinColumn(name = "opportunity_id")
private List<UserEntity> users;
#OneToOne
#JoinColumn(name = "mainuser_id")
private UserEntity mainUser;
}
When i search for a list of Users [find users], i've got a "stackoverflow" when mapping User.opportunity.
the bug was clear that the opportunity.mainUser refer to User which itself refer to the same opportunity.
Is there another way to design my models ?
For example create a boolean isMain in User Model ?
Try to specify relationship to UserEntity by adding mappedBy to annotatation
#Table(name = "opportunity")
public class OpportunityEntity
{
#Id
#Column(name = "id", unique = true, nullable = false)
private Long id;
#OneToMany
#JoinColumn(name = "opportunity_id")
private List<UserEntity> users;
#OneToOne(mappedBy="opportunity")
#JoinColumn(name = "mainuser_id")
private UserEntity mainUser;
}

Hibernate OneToMany relation doesn't map new data

I have two entities Courses and CourseUser. Courses mapped with OneToMany annotation to a CourseUser. After i add a CourseUser in a list of CourseUsers in Course and update it, new row appears in table CourseUser but it doesn't mapped to a Courses. If i call toString of courseUsers list from courses after update it will be empty.
#Entity
#Table(name = "COURSES")
public class Courses{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "course_id")
private int course_id;
#Column(name = "course_name", nullable = false)
private String courseName;
#Autowired
#OneToMany(mappedBy = "course", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private Set<CourseUser> courseUsers = new HashSet<>(0);
CourseUser entity:
#Entity
#Table(name = "COURSE_USERS",
uniqueConstraints = {#UniqueConstraint(columnNames = {"course_name", "user_name"})})
public class CourseUser {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "ev_id")
private int ev_id;
#Column(name = "course_name", nullable = false)
private String courseName;
#Column(name = "user_name", nullable = false)
private String userName;
#Column(name = "course_role")
private String courseRole;
#Column(name = "grade")
private int grade ;
#ManyToOne
#JoinColumn(name = "course_id")
private Courses course;
this is how i add new courseUser to a course :
Courses course = courseDAO.getCourse(id);
Set<CourseUser> courseUsers = course.getCourseUsers();
CourseUser newUser = new CourseUser();
newUser.setUserName(name);
newUser.setCourseRole(role);
newUser.setCourseName(course.getCourseName());
courseUsers.add(newUser);
course.setCourseUsers(courseUsers);
update(course);
and here is CoursesDAO update method:
public void update(Courses course) {
Session session = sf.openSession();
Transaction transaction = session.beginTransaction();
session.merge(course);
session.flush();
transaction.commit();
session.close();
}
At first, you have to save entity, which is referenced by id.
In your case, you have to save CourseUser at first, and then add it to Course.
For example:
Courses course = courseDAO.getCourse(id);
Set<CourseUser> courseUsers = course.getCourseUsers();
CourseUser newUser = new CourseUser();
newUser.setUserName(name);
newUser.setCourseRole(role);
newUser.setCourseName(course.getCourseName());
// this row is very important
// after thus operation newUser will have an id to be referenced
courseUserDto.save(newUser);
courseUsers.add(newUser);
course.setCourseUsers(courseUsers);
update(course);
Also, there is some redundant code that you wrote:
Set<CourseUser> courseUsers = course.getCourseUsers();
// ...
course.setCourseUsers(courseUsers);
course already stores reference to courseUsers.

OneToMany PersistentBag

I have a problem with storing OneToMany relationship with Hibernate.
What I got is AdvertisementData entity which looks as follows:
#Entity
#Table(name = "advertisement_data")
public class AdvertisementData {
#Id
#Column(name = "order_id", unique = true, nullable = false)
#GeneratedValue(generator = "gen")
#GenericGenerator(name = "gen", strategy = "foreign", parameters = #Parameter(name = "property", value = "order"))
private Long id;
#OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.MERGE, mappedBy = "advertisementData")
private List<KRPData> krpData;
//setters and getters
}
and KRPData which is defined as follows:
#Entity
public class KRPData {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String description;
#Type(type = "org.hibernate.type.SerializableToBlobType")
private List<String> images;
private String section;
#Type(type = "org.hibernate.type.SerializableToBlobType")
private List<String> filenames;
#ManyToOne
private AdvertisementData advertisementData;
//getters and setters
}
I can see that both entities are stored, however every time I fetch AdvertisementData, the results looks like:
KRPData is returned as PersistentBag without any data.
Hibernate version: 4.2.2.Final
Any ideas what could be the case?
Thank You in advance!

Joining with cross-reference table in hibernate and spring

I use hibernate and spring-data. There are two tables with many-to-many relationship.
#Entity
#Table(name = "FirstEntity")
public class FirstEntity {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "first_entity_id")
private Long id;
#Column(name = "first_entiry_name")
private String name;
/* getters and setters are below*/
}
#Entity
#Table(name = "SecondEntity")
public class SecondEntity {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "second_entity_id")
private Long id;
#Column(name = "second_entiry_name")
private String name;
#Column(name = "second_entiry_desc")
private String description;
/* getters and setters are below*/
}
And entity for cross-reference table.
#Entity
#Table(name = "FirstSecondEntity")
public class FirstSecondEntity {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "first_second_entity_id")
private Long id;
#Column(name = "first_entity_id")
private Long firstEntityId;
#Column(name = "second_entity_id")
private Long secondEntityId;
/* getters and setters are below*/
}
I need SELECT like this
SELECT FirstEntity.name, SecondEntity.name, SecondEntity.description FROM SecondEntity INNER JOIN FirstSecondEntity ON SecondEntity.id = FirstSecondEntity.secondEntityId INNER JOIN User ON FirstEntity.id = FirstSecondEntity.firstEntityId
i.e. I need all records from cross-reference table where instead of ids there is actual info from entities.
Inserting this query into #Query annotation in my CrudRepository-extended class doesn't work because of
ERROR [main][org.hibernate.hql.internal.ast.ErrorCounter] Path expected for join!
So I need your help.
Your join table is all screwed up. In this case, you actually don't even need the join table as a hibernate mapping:
In Second Entity add the following list:
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable(name = "FirstSecondEntity",
joinColumns = {
#JoinColumn(name = "first_entity_id",
nullable = false,
updatable = false) },
inverseJoinColumns = {
#JoinColumn(name = "second_entity_id",
nullable = false,
updatable = false) },
)
private List<FirstEntity> firstEntities;
In FirstEntity add the following list:
#ManyToMany(fetch = FetchType.LAZY,
mappedBy = "firstEntities")
private List<SecondEntity> secondEntities;

Categories

Resources