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.
Related
I am currently working on a project with following data structure:
public class PinaColadaId implements Serializable {
private UUID id;
#Temporal(TemporalType.TIMESTAMP)
private Date time;
// Constructor + Getters and Setters
}
#Entity
#Table(name = "pina_coladas")
#IdClass(PinaColadaId.class)
public class PinaColadaEntity {
#Column(columnDefinition = "char(255)")
#Type(type="org.hibernate.type.UUIDCharType")
private #Id UUID id;
private #Id #Temporal(TemporalType.TIMESTAMP) Date time;
#OneToOne(mappedBy = "entityID", cascade=CascadeType.ALL)
private PineappleWrapper pineapple;
#OneToMany(mappedBy = "entityID", cascade=CascadeType.ALL)
private List<CoconutWrapper> coconuts;
// Constructor + Getters and Setters
}
#Entity
public class PineappleWrapper {
private #Id #GeneratedValue long id;
private String manufacturer;
private String origin;
#OneToOne
private PinaColadaEntity entityID;
// Constructor + Getters and Setters
}
#Entity
public class CoconutWrapper {
private #Id #GeneratedValue long id;
private int shipmentNumber;
private int juice;
#ManyToOne
private PinaColadaEntity entityID;
// Constructor + Getters and Setters
}
The issue is that Spring Boot together with Hibernate and JPA correctly generate all the tables in my database, however when I attempt to store PineappleWrapper or CoconutWrapper, it stores all the values of PineappleWrapper and/or CoconutWrapper except for the id and time of the parent. The columns are generated yet they store the value "null".
Any and all help is much appreciated, -AwesomeDude091
Edit: I am aware of the JoinColumn annotation and it proposed implementation in my Wrapper classes, but I do not know how to use them with my two ID variables (id and time)
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;
// ...
}
I am new to hibernate and I am trying to implement a basic application that uses this schema (it does not follow the notation I just use it for clarity)
Here is the my classes
#Entity
#Table(name = "race")
public class Race {
#Id
#GeneratedValue
private UUID id;
private String name;
}
#Entity
#Table(name="np_character")
public class NPCharacter {
#Id
#GeneratedValue
private UUID id;
#OneToOne
private Race race;
private String name;
private int age;
}
#Entity
#Table(name="main_female_character")
public class MainFemaleCharacter {
#Id
#GeneratedValue
private UUID id;
#OneToOne
private Race race;
private String name;
private int age;
}
#Entity
#Table(name="copulation_registry")
public class CopulationRegistry {
// ??
private NPCharacter npCharacter;
// ??
private MainFemaleCharacter femCharacter;
private int times;
}
But I ran into the problem with copulation_registry class. I used everywhere OneToOne annotation, instead of using references to keys. But what I should do here? Pairs of id_femPlayer and id_npCharacter are unique.
Should I use EmbeddedId annotation or is it possible somehow to use association annotations to represent the same relation?
You can annotate class CopulationRegistry with #IdClass
#Entity
#IdClass(CopulationRegistryKey.class)
#Table(name="copulation_registry")
public class CopulationRegistry {
#Id
private NPCharacter npCharacter;
#Id
private MainFemaleCharacter femCharacter;
private int times;
}
public class CopulationRegistryKey{
private NPCharacter npCharacter;
private MainFemaleCharacter femCharacter;
}
I want to change Train.trainFares from transient to mapped to the TrainFare class. However, I want to limit the TrainFares to those that are active for the Train.ddate. How do I do this?
I have found a Hibernate Jira issue which I believe might be the source of my problems. Has anyone else come across this issue? Did you find a workaround?
#Entity
#Table(name = "TRAIN")
public class Train {
#EmbeddedId
private TrainPK id;
#Column
private String trainType;
#Transient
private List<TrainFare> trainFares;
#Embeddable
public static class TrainPK {
#Column
private String company;
#Column
private Date departDate;
#Column
private String trainNumber;
}
... setters & getters
}
#Entity
#Table(name = "SEATRATE")
public class SeatRate {
#EmbeddedId
private SeatRatePK id;
#Column
private Date expiryDate;
#Column
private String trainNumber;
#Embeddable
public static class SeatRatePK {
#Column
private String company
#Column
private Date effectiveDate;
}
... setters & getters
}
I'm building a small eclipse rcp with a little bit of JPA. Now something strange happens:
I create some TopCategories with some SubCategories, this works as intended. The inserts are printed in the log. I close my application and now the problem raises up:
The Categories have a relation to books
Book.java
#Entity
public class Book implements Serializable, PropertyChangeListener {
private static final long serialVersionUID = 4646743297687986216L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String name;
private boolean active = true;
#Temporal(TemporalType.TIMESTAMP)
private Date updated;
#Lob
private Set<Group> allowedGroups;
#Column(columnDefinition = "TEXT")
private String text;
private BookType type;
#ManyToOne
private TopCategory topCategory;
#ManyToOne
private SubCategory subCategory;
#OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private BookAttachment attachment;
#Transient
private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
// ordinary getter/setter
#PrePersist
#PreUpdate
private void updateUpdated() {
this.updated = new Date();
}
}
After restart and querying Book with this select b from Book all SubCategories which aren't used getting deleted. If a SubCategory has a relation to Book it stays in my DB. Why this occures?
Category.java
#MappedSuperclass
public class Category implements Serializable {
private static final long serialVersionUID = 6091963773161164543L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String name;
#Temporal(TemporalType.TIMESTAMP)
private Date updated;
#Enumerated(EnumType.STRING)
private CategoryType type;
#Transient
private List<Snippet> snippets = new LinkedList<Snippet>();
// ordinary getter/setter
#PrePersist
#PreUpdate
public void updateUpdated() {
this.updated = new Date();
}
}
TopCategory.java
#Entity
public class TopCategory extends Category {
#OneToMany(cascade = CascadeType.ALL)
private List<SubCategory> subCategories;
public TopCategory() {
setName("");
setSubCategories(new ArrayList<SubCategory>());
}
public List<SubCategory> getSubCategories() {
return subCategories;
}
public void setSubCategories(List<SubCategory> subCategories) {
this.subCategories = subCategories;
}
#Override
public void setType(CategoryType type) {
super.setType(CategoryType.topCategory);
}
SubCategory.java
#Entity
public class SubCategory extends Category {
#ManyToOne(cascade = CascadeType.ALL)
private TopCategory topCategory;
public TopCategory getTopCategory() {
return topCategory;
}
public void setTopCategory(TopCategory topCategory) {
this.topCategory = topCategory;
}
#Override
public void setType(CategoryType type) {
super.setType(CategoryType.subCategory);
}
}
I'm using Eclipselink 2.1.1.
Regards
Alright - I've found the problem: One of the result lists from my model is modified from a contentprovider - this is were not used SubCategories are removed, in case that the entity objects weren't detached, it caused the entitymanger to update.