Is there any way to delete entities from child entity using JPA? - spring-boot

I have 3 tables Table A, B, C. Table A is associated #OneToMany with Table B. Table B is associated #ManyToOne with Table C. Now when I find by Id of Table A, I am able to get details of A,B,C. But when I persist / delete, It is affecting only Table A&B. Table C is unaffected.
Is this possible in JPA to delete entities from child entity? Googled lot, but could not find any clue.
Below are the entity models of all the three tables
#Entity
#Table(name = "FEATUREMASTER")
#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
public class FeatureMaster implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#Column(name = "FGID")
private String featureid;
#Column(name = "FEATURENAME", nullable = false, unique = false)
private String featurename;
#Column(name = "DESCRIPTION", nullable = true, unique = false)
private String description;
#Column(name = "LIBNAME", nullable = true, unique = false)
private String libname;
#Column(name = "ISENABLED", nullable = false, unique = false)
private String isenabled;
#Column(name = "EDRULEGRP", nullable = true, unique = false)
private String edrulegrp;
// Do Not use - [orphanRemoval = true & CascadeType.ALL]- If used, deletion is not happening
#OneToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
#JoinColumn(name = "FGID")
private List<CfgMaster> parameters;
// Getters and Setters
}
#Entity
#Table(name = "CFGMASTER")
public class CfgMaster implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#EmbeddedId
private CfgMasterPK id;
#Column(name = "CONFIGNAME", length = 45, nullable = true, unique = false)
private String parameter_name;
#Column(name = "CONFIGTYPE", length = 20, nullable = true, unique = false)
private String type;
#Column(name = "SUBPARAM", nullable = true, unique = false)
private Integer subparam;
#Column(name = "CONFIGDESCRIPTION", nullable = true, unique = false)
private String description;
#Column(name = "CONFIGLIMITFROM", nullable = true, unique = false)
private String from;
#Column(name = "CONFIGLIMITTO", nullable = true, unique = false)
private String to;
#ManyToOne(cascade = {CascadeType.ALL}, optional = true, fetch = FetchType.LAZY )
// #ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, fetch = FetchType.LAZY)
#NotFound(action=NotFoundAction.IGNORE) // This is required to handle when no CfgData is found
#JoinColumns({
#JoinColumn(name = "FGID", insertable = false, updatable = false),
#JoinColumn(name = "DATAKEY", insertable = false, updatable = false)
})
private CfgData cfgData;
//Getters and Setters
}
#Entity
#Table(name = "CFGDATA")
public class CfgData implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
/*#EmbeddedId
private CfgDataPK id;*/
#Id
#Column(name = "FGID")
private String fgid;
#Id
#Column(name = "DATAKEY")
private String datakey;
#Column(name = "EPID", nullable = false, unique = false)
private int epid;
#Column(name = "RESERVED1", length = 45, nullable = true, unique = false)
private String reserved1;
#Column(name = "VALUE1", length = 100, nullable = true, unique = false)
private String value1;
#Column(name = "VALUE2", length = 100, nullable = true, unique = false)
private String value2;
//Getters and Setters
}
The problem I am facing is, I am not able to delete/save the entities of CfgData by passing FeatureMaster's primary id. Any operation I do is affecting only parent &child, not the grand child (CfgData) I tried a lot googling, but I cant find the solution.

Related

Spring specification query for one to many join and sum of field is grater then given value

I am creating filter using joining this three entity seeker_job_application,seeker_profile and seeker_experience. where I want achieve result as below query.
In filter I want to find out seeker_profile whose total_moth of experience should be grater then or equal to given value i.e 20, one seeker_profile has multiple experience so I need to group by profile and sum of their experience and then compare with given value. is it possible to do this using spring specification?
How to check that seeker total month of experience is grater then or equal to given value?
Relation between table is
seeker_job_application 1<-->1 seeker_profile 1<---->* seeker_experience
Want to achieve query like this
select r.sja_id,r.sp_id,r.name,r.company_name,r.total_month from (
select sja.id as sja_id , sp.id as sp_id , sp.`name`,se.company_name,sum(se.total_month) as total_month
from seeker_job_application sja
INNER JOIN seeker_profile sp on sp.id = sja.seeker_id
INNER JOIN seeker_experience se on se.seeker_id = sp.id
where job_id =1 group by sp.id ) as r where r.total_month > 20;
#Entity
#Table(name = "seeker_job_application")
#Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class SeekerJobApplication implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#NotNull
#Column(name = "seeker_id", nullable = false)
private Long seekerId;
#NotNull
#Column(name = "job_id", nullable = false)
private Long jobId;
#Column(name = "apply_date")
private Instant applyDate;
#Column(name = "profile_viewed")
private Boolean profileViewed;
#Column(name = "on_hold")
private Boolean onHold;
#Column(name = "interview_schedule")
private Boolean interviewSchedule;
#Column(name = "rejected")
private Boolean rejected;
#Column(name = "selected")
private Boolean selected;
#Column(name = "prefered_location_id")
private Long preferedLocationId;
#Column(name = "work_preference")
private String workPreference;
#Column(name = "resume_file_path")
private String resumeFilePath;
#Column(name = "status")
private String status;
#ManyToOne
#JoinColumn(name="seeker_id",referencedColumnName = "id", insertable = false, updatable = false)
private SeekerProfile seekerProfile;
#Data
#Entity
#Table(name = "seeker_profile")
#Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class SeekerProfile implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "id")
private Long id;
#Column(name = "name", nullable = false)
private String name;
#Column(name = "mobile_number", nullable = false)
private String mobileNumber;
#Column(name = "password")
private String password;
#Column(name = "email", nullable = false)
private String email;
#Column(name = "house_number")
private String houseNumber;
#Column(name = "address_line_1")
private String addressLine1;
#Column(name = "address_line_2")
private String addressLine2;
#Column(name = "city")
private String city;
#Column(name = "postcode")
private String postcode;
#Column(name = "state")
private String state;
#Column(name = "country")
private String country;
#Column(name = "website")
private String website;
#Column(name = "linkedin")
private String linkedin;
#Column(name = "facebook")
private String facebook;
#Column(name = "gender")
private String gender;
#Column(name = "dob")
private String dob;
#Column(name = "resume")
private String resume;
#Column(name = "wfh")
private String wfh;
#Column(name = "profile_completed")
private String profileCompleted;
#OneToOne
#JoinColumn(unique = true)
private Location preferedLocation;
#ManyToMany(fetch = FetchType.EAGER)
#JoinTable(name = "seeker_skill", joinColumns = { #JoinColumn(name = "seeker_id") }, inverseJoinColumns = { #JoinColumn(name = "skill_id") })
private Set<Skill> skills;
#OneToMany(fetch = FetchType.EAGER)
#JoinColumn(name="seeker_id",referencedColumnName = "id", insertable = false, updatable = false)
private Set<SeekerExperience> seekerExperiences;
#OneToMany
#JoinColumn(name="seeker_id",referencedColumnName = "id", insertable = false, updatable = false)
private Set<SeekerEducation> seekerEducation;
#Entity
#Table(name = "seeker_experience")
#Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class SeekerExperience implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#NotNull
#Column(name = "seeker_id", nullable = false)
private Long seekerId;
#NotNull
#Column(name = "job_title", nullable = false)
private String jobTitle;
#NotNull
#Column(name = "company_name", nullable = false)
private String companyName;
#NotNull
#Column(name = "start_date", nullable = false)
private String startDate;
#NotNull
#Column(name = "end_date", nullable = false)
private String endDate;
#Column(name = "total_month")
private Integer totalMonth;
#Column(name = "location")
private String location;
#Column(name = "role_description")
private String roleDescription;
Specification<SeekerJobApplication> specification = Specification.where(null);
specification = specification.and((root, query, cb) -> {
Join<SeekerJobApplication, SeekerProfile> seekerProfile=root.join(SeekerJobApplication_.seekerProfile);
Join<SeekerProfile, SeekerExperience> seekerExperience = seekerProfile.join(SeekerProfile_.seekerExperiences);
query.having(cb.greaterThanOrEqualTo(cb.sum(seekerExperience.get(SeekerExperience_.totalMonth)), criteria.getTotalExperience().getEquals()));
query.getRestriction();
});
This will give me result as below query
select sja.* from seeker_job_application sja
INNER JOIN seeker_profile sp on sja.seeker_id = sp.id
INNER JOIN seeker_experience se on se.seeker_id = sp.id
where sja.job_id = 1
GROUP BY sp.id
having sum(se.total_month) > 20

Why hibernate is throwing constraintViolationException?

Order Entity
#Entity
#Table(name = "Order",
indexes = {
#Index(name = "ORDER_X1", columnList = "REFERENCE_ID,SOURCE_ID"),
#Index(name = "ORDER_X2", columnList = "TYPE,STATUS")
}
)
#DiscriminatorColumn(name="PROCESSOR_TYPE", discriminatorType=DiscriminatorType.STRING, length = 80)
#SequenceGenerator(name="orderSeq", sequenceName="ORDER_SEQ")
#Inheritance(strategy= InheritanceType.JOINED)
public abstract class OrderEntity implements Serializable {
#Id
#GeneratedValue(strategy= GenerationType.SEQUENCE, generator="orderSeq")
private Long id;
#ManyToMany(cascade={CascadeType.MERGE})
#JoinTable(
name = "FILE_ORDER_MAP",
joinColumns = {#JoinColumn(name = "ORDER_ID")},
inverseJoinColumns = {#JoinColumn(name = "FILE_ID")}
)
private Set<TransferFile> transferFiles = new HashSet<>();
#Column(name = "TYPE")
#Enumerated(EnumType.STRING)
private OrderType type;
#Column(name = "AMOUNT", precision = 12, scale = 2)
private LcMoney amount;
#Column(name = "STATUS")
#Enumerated(EnumType.STRING)
private OrderStatus reconStatus;
#Type(type = LcUtc.JPA_JODA_TIME_TYPE)
#Column(name = "STATUS_D", nullable = false)
#LcDateTimeUtc()
private DateTime reconStatusDate;
#Column(name = "REFERENCE_ID")
private Long referenceId;
#Column(name = "SOURCE_ID")
private Long sourceId;
#Column(name = "ACCOUNT_ID")
private Long accountId;
#Column(name = "PROCESSOR_TYPE", insertable = false, updatable = false)
#Enumerated(EnumType.STRING)
private OrderProcessorType processorType;
#Type(type = LcUtc.JPA_JODA_TIME_TYPE)
#Column(name = "TX_EXECUTION_D")
#LcDateTimeUtc()
private DateTime executedDate;
#Type(type = LcUtc.JPA_JODA_TIME_TYPE)
#Column(name = "CREATE_D")
#LcDateTimeUtc()
private DateTime createDate;
#Column(name = "IS_ON_DEMAND")
#Type(type = "yes_no")
private boolean isOnDemand;
#ManyToOne(fetch = FetchType.LAZY, optional = true, cascade = {CascadeType.PERSIST})
#JoinColumn(name="PAYER_ID", nullable=true)
private Payer payer;
#OneToMany(cascade = CascadeType.ALL)
#JoinColumn(name = "ORDER_ID", referencedColumnName = "ID")
private List<OrderTransaction> orderTransactions;
#OneToMany(cascade = {CascadeType.ALL})
#JoinColumn(name = "ORDER_ID", referencedColumnName = "ID",
foreignKey = #ForeignKey(name = "FK_ORDER")
)
private List<MatchResult> matchResults;
#Version
#Column(name = "VERSION")
private Integer version;
#Embedded
#AttributeOverrides({
#AttributeOverride(name = "externalSourceId", column = #Column(name = "TRANS_EXT_SRC_ID")),
#AttributeOverride(name = "externalId", column = #Column(name = "TRANS_EXT_REF_ID"))
})
private LcExternalIdEntity transExtId;
#PreUpdate
#PrePersist
public void beforePersist() {
if (reconStatusDate != null) {
reconStatusDate = reconStatusDate.withZone(DateTimeZone.UTC);
}
if (executedDate != null) {
executedDate = executedDate.withZone(DateTimeZone.UTC);
}
if (createDate != null) {
createDate = createDate.withZone(DateTimeZone.UTC);
}
}
// getters and setters
}
//controller method
public Response processFile(){
// separate trasaction
service.readFileAndCreateOrders(); // read files and create orders in new status
List<Order> newOrders = service.getNewOrders();
for( Order order: newOrders){
service.processOrder(order); // separate transaction
}
}
#Transaction
void processOrder(OrderEntity order){
matchResultJpaRepository.save(orderEntity.id);
log.info("Saving matchId={} for order={}", match.getId(), order.getId());
// create new transaction and add to order
OrderTransaction transaction = createNewTransaction(order);
order.getTransactions().add(transaction);
order.setStatus("PROCESSED");
log.info("Saving Order id={}, Type={}, Status={} ", order.getId(), order.getType(), order.getStatus());
orderRepository.save(order);
}
I am seeing this below error.
ORA-01407: cannot update ("PAYMENTS"."MATCH_RESULT"."ORDER_ID") to NULL
This endpoing is not exposed to user. There is a batch job which invokes this endpoint.
This code has been there for atleast a year and this is the first time i am seeing this.
This happened only once and for only one call. I am seeing both the logs printed. I am puzzled why I am seeing above error complaining about NULL order id. From the logs, we can confirm that the order id is definitely not null.
Any idea why this is happening? What can be done to fix this?

How to retrieve data based on inverseColumn data using CrudRepository in springboot?

I have two tables i.e. users and events. Users table will be filled when new user will sign up. Later same user can create calendar events. so events table will be filled and users_events will keep mapping of events based on user.
I would like to find all events based on logged in userId. so here is query, it should return data based on it.
select * from events where eventid in (select eventId from users_event where id_user=x ). Here is my Users and Event Entity class.
User.java
#Entity
#Table(name = "users")
public class User {
#Id
#GenericGenerator(name = "generator", strategy = "increment")
#GeneratedValue(generator = "generator")
#Column(name = "id", nullable = false)
private Long id;
#Column(name = "first_name", nullable = false)
private String firstName;
#Column(name = "family_name", nullable = false)
private String familyName;
#Column(name = "e_mail", nullable = false)
private String email;
#Column(name = "phone", nullable = false)
private String phone;
#Column(name = "language", nullable = false)
private String language;
#Column(name = "id_picture")
private String pictureId;
#Column(name = "login", nullable = false)
private String login;
#Column(name = "password", nullable = false)
private String password;
#Column(name = "birth_date")
private Date birthDate;
#Column(name = "enabled")
private Boolean enabled;
//getter and setter
Event.java
#Entity
#Table(name = "events")
public class Event {
#Id
#GenericGenerator(name = "generator", strategy = "increment")
#GeneratedValue(generator = "generator")
#Column(name = "eventId", nullable = false)
private Long eventId;
#Column(name = "title", nullable = false)
private String title;
#Column(name = "description", nullable = true)
private String description;
#Column(name = "startAt", nullable = false)
#Temporal(TemporalType.TIMESTAMP)
private Date startAt;
#Column(name = "endAt", nullable = true)
#Temporal(TemporalType.TIMESTAMP)
private Date endAt;
#Column(name = "isFullDay", nullable = false)
private Boolean isFullDay;
#ManyToMany(fetch = FetchType.EAGER)
#JoinTable(name = "users_event", joinColumns = { #JoinColumn(name = "id_event", referencedColumnName = "eventId") }, inverseJoinColumns = { #JoinColumn(name = "id_user", table = "users", referencedColumnName = "id") })
private Set<User> user = new HashSet<User>();
/getter and setter
EventRepo.java
public interface EventRepo extends CrudRepository<Event, Long> {
Event findByUser(Set<User> user);
}
I am trying to implement something, which can give me output of this query.
select * from events where eventid in (select eventId from users_event where id_user=x )
here is my implementation.any input please?
#RequestMapping(value = "/events", method = RequestMethod.GET)
public #ResponseBody List<Event> getEvents() {
logger.debug("get event list");
User x=new User();
x.setId(1);
Set<User> user= new HashSet();
user.add(x);
return (List<Event>) eventRepo.findByUser(user);
}
Just add a following method to your EventRepo:
List<Event> findAllByUserId(Long userId);
And modify your controller to something like this:
#RequestMapping(value = "/events", method = RequestMethod.GET)
public List<Event> getEvents() {
return eventRepo.findAllByUserId(1L);
}

Spring OneToMany relation with composite key to another with a composite key

I want to have a ManyToOne relation between 2 classes (Chapter & Camera). A chapter object contains many Camera objects.
The problem is my parent class (Chapter) already has a composite key.
Chapter composite key:
#Embeddable
public class ChapterKey implements Serializable {
#Column(name = "Chapter_ID", nullable = false)
private int chapterID;
#Column(name = "Operation_FK", nullable = false)
private int operationFK;
}
Chapter class:
#Entity
public class Chapter implements Serializable
{
private static final long serialVersionUID = 1L;
#EmbeddedId
private ChapterKey chapterKey;
#Column(name="Chapter_Name")
private String chapterName;
#Column(name="Chapter_Description")
private String chapterDescription;
#Column(name="Chapter_View_Range")
private int chapterViewRangeInterval;
#Column(name="Chapter_Video_Length")
private int chapterVideoLength;
}
Camera key:
#Embeddable
public class CameraKey implements Serializable {
#Column(name = "Camera_ID", nullable = false)
private int cameraID;
#Column(name = "Chapter_FK", nullable = false)
private int chapterFK;
#Column(name = "Operation_FK", nullable = false)
private int operationFK;
}
Camera class:
#Entity
public class Camera implements Serializable
{
private static final long serialVersionUID = 1L;
#EmbeddedId
private CameraKey cameraKey;
#Column(name="Camera_Description")
private String cameraDescription;
#Column(name="Camera_Usage")
private int cameraUsage;
#Column(name="Video_URL")
private String videoURL;
}
My question is, how do i make a OneToMany relationship between those 2 classes?
This answer for chapter side pk(Chapter_ID, Operation_FK) and camera side pk(camera_id,chapter_fk,operation_fk)
ER for is below.
Chapter.class is
#Entity
public class Chapter implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
protected ChapterPK chapterPK;
#Basic(optional = false)
#Column(name = "chapter_name", nullable = false, length = 12)
private String chapterName;
#Basic(optional = false)
#Column(name = "chapter_description", nullable = false, length = 12)
private String chapterDescription;
#Basic(optional = false)
#Column(name = "chapter_Vvew_range", nullable = false)
private int chapterVvewrange;
#Basic(optional = false)
#Column(name = "chapter_video_length", nullable = false)
private int chapterVideoLength;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "chapter")
private Collection<Camera> cameraCollection;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "chapter1")
private Collection<Camera> cameraCollection1;
}
ChapterPK.class
#Embeddable
public class ChapterPK implements Serializable {
#Basic(optional = false)
#Column(name = "chapter_id", nullable = false)
private int chapterId;
#Basic(optional = false)
#Column(name = "operation_fk", nullable = false)
private int operationFk;
}
Camera.class
#Entity
public class Camera implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
protected CameraPK cameraPK;
#Basic(optional = false)
#Column(name = "camera_description", nullable = false, length = 12)
private String cameraDescription;
#Basic(optional = false)
#Column(name = "camera_usage", nullable = false)
private int cameraUsage;
#Basic(optional = false)
#Column(name = "video_url", nullable = false)
private int videoUrl;
#JoinColumn(name = "chapter_fk", referencedColumnName = "chapter_id", nullable = false, insertable = false, updatable = false)
#ManyToOne(optional = false)
private Chapter chapter;
#JoinColumn(name = "operation_fk", referencedColumnName = "operation_fk", nullable = false, insertable = false, updatable = false)
#ManyToOne(optional = false)
private Chapter chapter1;
}
CameraPK.class
#Embeddable
public class CameraPK implements Serializable {
#Basic(optional = false)
#Column(name = "camera_id", nullable = false)
private int cameraId;
#Basic(optional = false)
#Column(name = "chapter_fk", nullable = false)
private int chapterFk;
#Basic(optional = false)
#Column(name = "operation_fk", nullable = false)
private int operationFk;
}
In here both side has two way binding.
This is ER for pk(camera_id) & pk(chapter_id,operation_fk) problem
This is a Chapter class.
#Entity
public class Camera implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#Column(name = "camera_id", nullable = false)
private Integer cameraId;
#Basic(optional = false)
#Column(name = "camera_description", nullable = false, length = 12)
private String cameraDescription;
#Basic(optional = false)
#Column(name = "camera_usage", nullable = false)
private int cameraUsage;
#Basic(optional = false)
#Column(name = "video_url", nullable = false)
private int videoUrl;
#JoinColumn(name = "chapter_fk", referencedColumnName = "chapter_id", nullable = false)
#ManyToOne(optional = false, fetch = FetchType.EAGER)
private Chapter chapterFk;
#JoinColumn(name = "operation_fk", referencedColumnName = "operation_fk", nullable = false)
#ManyToOne(optional = false, fetch = FetchType.EAGER)
private Chapter operationFk;
}
this is ChapterPK.class that define primary key of your chapter class. it has composite primary key.
#Embeddable
public class ChapterPK implements Serializable {
#Basic(optional = false)
#Column(name = "chapter_id", nullable = false)
private int chapterId;
#Basic(optional = false)
#Column(name = "operation_fk", nullable = false)
private int operationFk;
}
finally camera.class
#Entity
public class Chapter implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
protected ChapterPK chapterPK;
#Basic(optional = false)
#Column(name = "chapter_name", nullable = false, length = 12)
private String chapterName;
#Basic(optional = false)
#Column(name = "chapter_description", nullable = false, length = 12)
private String chapterDescription;
#Basic(optional = false)
#Column(name = "chapter_Vvew_range", nullable = false)
private int chapterVvewrange;
#Basic(optional = false)
#Column(name = "chapter_video_length", nullable = false)
private int chapterVideoLength;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "chapterFk", fetch = FetchType.EAGER)
private Collection<Camera> cameraCollection;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "operationFk", fetch = FetchType.EAGER)
private Collection<Camera> cameraCollection1;
}
In here I use two way binding in both chapter and camera classes. if you are using composite primary key. you have to manage additional embedded primary key object.

JPA Hibernate MapsId for grand child

I am trying to save an entity in JPA 2.1.
I have three tables - MVCollection, MVCollectionVersion (which is versions of MVCollection) and MVBelongsCollection(which is the items belonging to a version).
The Primary Key of MVCollection is a generated sequence number.
When I generate a collection with a version (without any items) I am using #MapsId, and the ID generated is used within the child. However I cannot seem to understand how I can replicate this with the items.
Here are snippets from the code so far :
#Entity
public class MVCollection {
#GeneratedValue(strategy = GenerationType.SEQUENCE,
generator = "MVCOLLECTION_SEQ")
#SequenceGenerator(name = "MVCOLLECTION_SEQ",
sequenceName = "VMD.MVCOLLECTION_SEQ")
#Id
#Column(name = "MVCOLLECTIONID")
private Long id;
MVCollectionVersion
#Entity
public class MVCollectionVersion {
#EmbeddedId
#AttributeOverrides({
#AttributeOverride(name = "versionId", column = #Column(name = "MVCVSNID")) })
private MVCollectionVersionId id;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumns({
#JoinColumn(name = "MVCOLLECTIONID", referencedColumnName = "MVCOLLECTIONID"),
})
#MapsId("mvCollectionId")
private MVCollection mvCollection;
#OneToMany(fetch = FetchType.LAZY, mappedBy="mvCollectionVersion", cascade={CascadeType.MERGE, CascadeType.PERSIST})
private List<MVBelongsCollection> mvCollectionItems;
MVCollectionId
#Embeddable
public class MVCollectionVersionId implements java.io.Serializable {
/**
*
*/
private static final long serialVersionUID = 2551937096790427792L;
private Long mvCollectionId;
private Integer versionId;
MVBelongsCollection
#Entity
public class MVCollectionItems
#EmbeddedId
#AttributeOverrides({
#AttributeOverride(name = "managedViewId", column = #Column(name = "MANAGEDVIEWID")),
#AttributeOverride(name = "mvCollectionId", column = #Column(name = "MVCOLLECTIONID")),
#AttributeOverride(name = "versionId", column = #Column(name = "MVCVSNID")) })
private MVBelongsCollectionId id;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumns({
#JoinColumn(name = "MVCOLLECTIONID", referencedColumnName = "MVCOLLECTIONID"),
#JoinColumn(name = "MVCVSNID", referencedColumnName = "MVCVSNID") })
private MVCollectionVersion mvCollectionVersion;
and finally MVBelongsCollectionId
#Embeddable
public class MVBelongsCollectionId implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
#Column ( name = "MANAGEDVIEWID", nullable = false, precision = 38)
private Long managedViewId;
#Column ( name = "MVCOLLECTIONID", nullable = false, precision = 38)
private Long mvCollectionId;
#Column ( name = "MVCVSNID", nullable = false, precision = 38)
private Integer versionId;
if I try to create a collection with a version and with belongsCollection items, the create fails as it states the mvCollectionId field is null
"ORA-01400: cannot insert NULL into ("VMD"."MVBELONGSCOLLECTION"."MVCOLLECTIONID")"
Therefore I tried to add #MapsId as I had done with MVCollectionVersion.
public class MVBelongsCollection {
/**
* primary key
*/
#EmbeddedId
#AttributeOverrides({
#AttributeOverride(name = "managedViewId", column = #Column(name = "MANAGEDVIEWID")),
//#AttributeOverride(name = "mvCollectionId", column = #Column(name = "MVCOLLECTIONID")),
#AttributeOverride(name = "versionId", column = #Column(name = "MVCVSNID")) })
private MVBelongsCollectionId id;
/**
* collection that this joins to.
*/
#ManyToOne(fetch = FetchType.LAZY)
#MapsId("mvCollectionId")
#JoinColumns({
#JoinColumn(name = "MVCOLLECTIONID", referencedColumnName = "MVCOLLECTIONID"),
#JoinColumn(name = "MVCVSNID", referencedColumnName = "MVCVSNID") })
private MVCollectionVersion mvCollectionVersion;
However in Eclipse, this shows an error on the #ManyToOne Annotation of
The type of the ID mapped by the relationship 'mvCollectionVersion' does not agree with the primary key class of the target entity.
If I start the process, I get
Caused by: org.hibernate.MappingException: Repeated column in mapping for entity: MVBelongsCollection column: MVCVSNID (should be mapped with insert="false" update="false")
I have tried adding insertable = false, and updatable = false to my #JoinColumn, the #AttributeOVerride and the underlying ID class but still get the same error.
This only happens when the #MapsId is present.
I am now at a loss how I get the MVBelongsCollection to use the generated MVCollectionId, or how I can stop both the eclipse and the runtime error.
If anyone can help I would be grateful.
Thanks in advance
I found the error of my ways...
I needed to use the same embeddedId throughout.
Therefore the MVBelongsCollectionId needed to change to include the embedded id of the parent class:
#Embeddable
public class MVBelongsCollectionId implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
#Embedded
#AttributeOverrides( {
#AttributeOverride(name = "mvCollectionId", column = #Column(name = "MVCOLLECTIONID", nullable = false, precision = 38, scale = 0)),
#AttributeOverride(name = "versionId", column = #Column(name = "MVCVSNID", nullable = false, precision = 8, scale = 0))
})
MVCollectionVersionId collectionVersionId;
#Column ( name = "MANAGEDVIEWID", nullable = false, precision = 38)
private Long managedViewId;
....

Resources