How to implement Composite Primary Key in Hibernate? - java

I have two tables with primary keys questionNumber and assessmentId. I want to use these two to make them composite in two different tables. Is this possible. Should I add something to this to make it work. OR is there another way to implement it. OR should I add question meta data to question and just used the composite key in AnswerKey
Question
#Entity
#Getter
#Setter
public class Question implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int questionId;
private int questionNumber;
private String assessmentId;
private QuestionTypes questionType;
private String questionText;
private String questionURL;
private QuestionStatus questionStatus;
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
#JoinColumn(name = "questionNumber", referencedColumnName = "questionNumber")
private List<QuestionOption> questionOptions;
//Constructor
// Getter and setter
}
Assessment
#Entity
#JsonIgnoreProperties({"questionList"})
public class Assessment {
#Id
private String assessmentId;
private String assessmentTopic;
private String assessmentSubTopic;
private String assessmentLevel;
private String createdBy;
private String rating;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "assessmentId", fetch = FetchType.LAZY)
private List<Question> questionList;
//Constructor
//Setter and getter
}
QuestionMetaData
#Entity
public class QuestionMetaData {
#Id
private QuestionAssessmentKey questionAssessmentKey;
private String topicName;
private String subtopicName;
private QuestionComplexity complexity;
private String conceptName;
//Getter and setter
//Constructor
}
AnswerKey
#Entity
public class AnswerKey {
#Id
private QuestionAssessmentKey questionAssessmentKey;
private Character answer;
//Constructor
// Setter and getter
}
Key
#Embeddable
public class QuestionAssessmentKey implements Serializable {
private int questionNumber;
private String assessmentId;
//Constructor
//Setter and Getter
}

These are "derived identities", so your mappings should like this:
#Entity
public class Assessment {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private String assessmentId;
private String assessmentTopic;
private String assessmentSubTopic;
private String assessmentLevel;
private String createdBy;
private String rating;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "assessment", fetch = FetchType.LAZY)
private List<Question> questionList;
// ...
}
#Entity
public class Question implements Serializable {
#EmbeddedId
private QuestionAssessmentKey questionAssessmentKey;
#ManyToOne
#MapsId("assessmentId") // maps assessmentId attribute of embedded id
private Assessment assessment;
private QuestionTypes questionType;
private String questionText;
private String questionURL;
private QuestionStatus questionStatus;
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
#JoinColumn(name = "questionNumber", referencedColumnName = "questionNumber")
private List<QuestionOption> questionOptions;
// ...
}
#Entity
public class QuestionMetaData {
#EmbeddedId
private QuestionAssessmentKey questionAssessmentKey;
private String topicName;
private String subtopicName;
private QuestionComplexity complexity;
private String conceptName;
#ManyToOne
#MapsId("assessmentId") // maps assessmentId attribute of embedded id
private Assessment assessment;
// ...
}
#Entity
public class AnswerKey {
#EmbeddedId
private QuestionAssessmentKey questionAssessmentKey;
private Character answer;
#ManyToOne
#MapsId("assessmentId") // maps assessmentId attribute of embedded id
private Assessment assessment;
// ...
}
#Embeddable
public class QuestionAssessmentKey implements Serializable {
private String assessmentId;
private int questionNumber;
// ...
}

Related

I can't get field from main table in json

From Postman I perform the query to the secondary table and the primary field of the parent table is not shown:
view image:
I need to see: identification_number
This is the daughter table:
#Entity
#Table(name="accounts")
public class Account {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long account_number;
private Date open_date;
private byte status;
private String account_type;// normalizar
private String bank;// normalizar
#JsonBackReference
#ManyToOne(cascade=CascadeType.ALL)
#JoinColumn(name="identification_number")
private Customer customer = new Customer();
This is the parent table:
#Entity
#Table(name="customers")
public class Customer implements Serializable{
private static final long serialVersionUID = 1L;
#Id
private String identification_number;
private String identification_type;//Normalizado
private String name;
private String last_name;
private String email;
private String cell_phone_number;
private String address;
#JsonManagedReference
#OneToMany(mappedBy = "customer", cascade = CascadeType.ALL)
//private List <Account> account = new ArrayList<>();
private Set<Account> account = new HashSet<Account>();
please help

Add foreign key using hibernate and jpa

Those are my classes:
#Entity
#Table(name="assessment")
public class AssesmentProperties {
#Id
#Column(name="AssessmentId")
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long AssessmentId;
#Column(unique=true,nullable=false)
private String AssessmentName;
private String AssessmentLevel;
private String Specialization;
private int time;
private String keywords;
private int NoOfSections;
//getters and setters
}
#Embeddable
public class SettingsPrimary implements Serializable {
private Long AssessmentId;
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long Section;
//getters and setters
}
#Entity
#Table(name="section")
public class SectionProperties {
#EmbeddedId
private SettingsPrimary PrimaryKey;
private String SectionType;
private int Weightage;
private int time;
private int NoOfQuestions;
//getters and setters
}
In the table section I need to create assessment_id as FK to assessment table and set cascade on delete. I have tried to do it with different ways but without success.
Maybe this could help you.
#Entity
#Table(name="section")
public class SectionProperties {
#Id
private Long PrimaryKey;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "assessment_id", referencedColumnName="AssessmentId")
private AssesmentProperties AssesmentProperties;
private String SectionType;
private int Weightage;
private int time;
private int NoOfQuestions;
//getters and setters
}
I changed the SectionProperties id to a Long and mapped the AssessmentProprties into a ManytoOne prop.
This way, always that a AssessmentProperties binded to a Section will be deleted, the associated SectionProperties will too.

How can i create only one record with Hibernate JPA Annotation

I have got 3 entity. These are: Tweet,Thread and Media. I am using Hibernate JPA Annotations. When i save one Thread object, it must trigger to tweet and automatically tweet must saved like thread and Tweet's "media" must saved of course.
You can see my entity class as below. Right now i'm working on Tweet beetween Thread. When i use these code, The number of thread is being recorded as much as tweet object. But i want that only one record inside thread.
Process must be like that after saved thread:
add a new record to Thread table. (only one row)
add all tweet to tweet table(all of "threadid" column same because these tweets belong only one thread!)
add all media to media table(all of "tweetid" column same )
Tweet Table:
#Entity
#Table(name = "tbl_tweet")
public class Tweet implements Serializable {
#Id
#GeneratedValue
private long id;
#Column(name = "tweetid")
private String tweetID;
private String parentTweetID;
private String avatar;
private String owner_name;
private String owner_nick;
private String content;
private String sent_time;
private String sent_date;
private String retweet_count;
private String like_count;
private String owner_link;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name="threadid")
private Thread thread;
#OneToMany(mappedBy = "tweet",fetch = FetchType.LAZY,cascade = {CascadeType.PERSIST,CascadeType.MERGE})
private List<Media> mediaURLs;
Thread Table:
#Entity
#Table(name = "tbl_thread")
public class Thread implements Serializable {
#Id
#GeneratedValue
private Long id;
#Column(name = "threadid")
private String threadID;
#Transient
private List<Tweet> listOfTweets;
Media Table:
#Entity
#Table(name = "tbl_media")
public class Media implements Serializable {
#Id
#GeneratedValue
private long id;
private String mediaID;
private String mediaType;
private String mediaUrl;
private String mediaUrlHttps;
private String mediaVideoUrl;
#ManyToOne
#JoinColumn(name = "tweetid")
private Tweet tweet;
My expected and actual results:
http://prntscr.com/mkaul5
I changed that way. Right now it's working good. Long live annotations!
Tweet Table:
#Entity
#Table(name = "tbl_tweet")
public class Tweet implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#Column(unique = true,nullable = false,name = "tweetID")
private String tweetID;
private String parentTweetID;
private String avatar;
private long owner_id;
private String owner_name;
private String owner_nick;
private String content;
private String sent_time;
private String sent_date;
private String retweet_count;
private String like_count;
#Transient
private String quotedTweetHtml;
#Transient
#JoinColumn(name = "threadid",referencedColumnName = "id")
private Thread thread;
#OneToMany(cascade = CascadeType.PERSIST,fetch = FetchType.EAGER)
#JoinColumn(name = "tweetID")
private List<Media> mediaURLs;
Thread Table:
#Entity
#Table(name = "tbl_thread")
public class Thread implements Serializable {
#Id
#GeneratedValue
private Long id;
#Column(name = "threadid")
private String threadID;
#OneToMany(cascade = CascadeType.PERSIST,fetch = FetchType.EAGER)
#JoinColumn(name = "threadid")
private List<Tweet> listOfTweets;
Media Table:
#Entity
#Table(name = "tbl_media")
public class Media implements Serializable {
#Id
#GeneratedValue
private long id;
private String mediaID;
private String mediaType;
private String mediaUrl;
private String mediaUrlHttps;
private String mediaVideoUrl;
#Transient
#JoinColumn(name = "tweetID")
private Tweet tweet;

Confusion with mapping in hibernate

I currently have 3 tables Assessment, Question and QuestionOption. Each assessment has some questions and each question has some question options. Initially I started our with #OneToMany mappings for these but later one due to the fields that I have I had to had composite keys in Question so the entire mapping changed. I am not satisfied with the current state. Can someone help me in mapping the tables.
The main reason I had to do this was that while instering questions, I realised that question number can be the same across multiple assessments. So I made it a composite key with questionNumber+assessmentId. Also the same thought process with question option. where the same question options can exist along different questions. How can and avoid this and keep it simple.
Assessment
#Entity
#JsonIgnoreProperties({"questionList"})
public class Assessment {
#Id
private String assessmentId;
private String assessmentTopic;
private String assessmentSubTopic;
private String assessmentLevel;
private String createdBy;
private String rating;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "assessment", fetch = FetchType.LAZY)
private List<Question> questionList;
//Getters and setters
}
Question
#Entity
#Getter
#Setter
#JsonIgnoreProperties({"assessment"})
public class Question implements Serializable {
#EmbeddedId
private QuestionAssessmentKey questionAssessmentKey;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "assessmentId", insertable = false, updatable = false)
private Assessment assessment;
private String questionText;
private String questionURL;
private QuestionStatus questionStatus;
// private int questionNumber;
private QuestionTypes questionType;
//Getters and Setters
}
QuestionAssessmentKey- The composite key
#Embeddable
public class QuestionAssessmentKey implements Serializable {
private int questionNumber;
private String assessmentId;
//Getters and setters
}
QuestionOption
#Entity
public class QuestionOption {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int questionOptionId;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumns({
#JoinColumn(name="assessmentId", referencedColumnName = "assessmentId"),
#JoinColumn(name="questionNumber", referencedColumnName = "questionNumber")
})
private Question question;
private Character questionOption;
private String questionOptionText;
//Getters and Setters
}

GAE JPA Embedded Annotation Issue

Ok so I have an Entity School.
#Entity
public class School implements Serializable
{
private static final long serialVersionUID = -854333301529125138L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long ID;
private String Type;
private String Name;
private String City;
private String Country;
#OneToOne(cascade = CascadeType.PERSIST,fetch=FetchType.LAZY)
private Info information;
#OneToMany(cascade = CascadeType.PERSIST, mappedBy="school",fetch=FetchType.LAZY)
private List<Contact> Contacts;
#OneToMany(cascade = CascadeType.PERSIST, mappedBy="school",fetch=FetchType.LAZY)
private List<Student> students= new ArrayList<Student>();
// more fields and getters and setters.
The Student Class contains lots of student information, and the student transcripts and is as follows
#Entity
public class Student implements Serializable
{
private static final long serialVersionUID = 5426530769458891752L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Key ID;
#ManyToOne
private School school;
private long SID;
private final long TSTAMP;
private String FName;
private String LName;
private String Email;
private String SchoolName;
#OneToOne(cascade = CascadeType.ALL,fetch=FetchType.LAZY)
private StudentInfo studentInf = new StudentInfo ();
#OneToOne(cascade = CascadeType.ALL,fetch=FetchType.LAZY)
private Transcript transcript;
// more fields and getters and setters.
the Transcript Class in the Student Class is as follows
#Entity
public class Transcript
{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Key ID;
#OneToOne(cascade = CascadeType.ALL, mappedBy="transcript",fetch=FetchType.LAZY)
private Student student;
#Embedded
private Course1 c1;
#Embedded
private Course2 c2;
#Embedded
private Course3 c3;
//... ect
public Transcript()
{
this.c1= new Course1();
this.c2= new Course2();
this.c3= new Course3();
// ... ect
}
// more fields and getters and setters.
and finally here is a sample course class
#Embeddable
public class Course1 implements Serializable
{
/**
*
*/
private static final long serialVersionUID = -7643055124732162110L;
private final String CourseTitle = "Course 1 Title";
private boolean MileStone1 = false;
private boolean MileStone2 = false;
// ... ect ... getters and setters
}
All the classes Enhance without a problem and the server runs, but as soon as a Student Instance is created, it results in a total catastrophe in GAE dev server and I have tried alot of possible options with the same error message:
"java.lang.IllegalArgumentException: org.datanucleus.exceptions.NucleusUserException: You have a field db.Entity.student.Student.transcript that has type db.Entity.Courses.Transcript but this type has no known metadata. Your mapping is incorrect"
I would very very much appreciate an explanation on why this is happening and how to fix it while keeping the logical relations

Categories