JPA update record is failing due to #OneToMany - java

I have a very small doubt regarding #OneToMany mapping.
I have a model student and another model attendance.
A student can have multiple attendance. but student model should only be able to retrieve the attendance info.
But when I am trying to change some student info I am getting below error as it is trying to update attendance record.
here is my mapping
#Entity
#Table(name="student_detail")
#Getter #Setter
public class StudentDetailsModel {
#Id
#Column(name="reg_no",updatable = false, nullable = false)
private String regNo;
#OneToMany(fetch = FetchType.LAZY, cascade = { CascadeType.ALL })
#JoinColumn(name = "reg_no")
private List<AttendanceModel> attendances;
}
and the exception I a getting.
update
student_detail
set
address=?,
alt_contact_number=?,
blood_group=?,
contact_number=?,
dob=?,
father_name=?,
first_name=?,
gender=?,
last_name=?,
middle_name=?,
mother_name=?,
photo_url=?,
school_id=?
where
reg_no=?
Hibernate:
update
attendance
set
reg_no=null
where
reg_no=?
2019-01-13 12:12:52.922 WARN 10708 --- [nio-8081-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 0, SQLState: 23502
2019-01-13 12:12:52.923 ERROR 10708 --- [nio-8081-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper : ERROR: null value in column "reg_no" violates not-null constraint
Detail: Failing row contains (null, 1, 2019-01-05, t, 2).
2019-01-13 12:12:52.926 INFO 10708 --- [nio-8081-exec-1] o.h.e.j.b.internal.AbstractBatchImpl : HHH000010: On release of batch it still contained JDBC statements
org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [reg_no]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
my attenance model is as follows
#Entity
#Table(name="attendance")
#Getter #Setter
public class AttendanceModel {
//#EmbeddedId
//private AttendanceId attendanceId;
#Id
#Column(name="attendance_id")
private long id;
#Column(name="reg_no")
private String regNo;
#Column(name="subject_id")
private long subjectId;
#Column(name="class_date")
private Date classDate;
#Column(name="present")
private boolean present;
}

Could you show me Student Model.If i look your code post : You using Unidirectional relationship.
I think it must :
#OneToMany(fetch = FetchType.LAZY , cascade = CascedeType.ALL)
#JoinColumn(name="attendance_id")
private List<AttendanceModel> attendances = new ArrayList<>();

Related

Hibernate mapping error while inserting child record

I have two entity class as below -
public class Parent {
#Id
private Integer parentId;
private String name;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "parent", cascade = CascadeType.ALL)
private List<Child> children;
}
public class Child {
#Id
private Integer childId;
private String name;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "parentId", insertable = false, updatable = true, nullable = false)
private Parent parent;
}
#RestController
public class ParentController {
#Autowired
private ParentRepo repo;
#GetMapping("/parent")
public void get() {
Child c1 = Child.builder().childId(1).name("s1").build();
Child c2 = Child.builder().childId(2).name("s2").build();
List<Child> children = new ArrayList<>();
children.add(c1);
children.add(c2);
Parent parent = Parent.builder().parentId(1).name("PARENT")
.children(children)
.build();
Parent savedParent = repo.save(parent);
}
}
Tables -
CREATE TABLE public.parent
(
parent_id integer NOT NULL,
name character varying(255) COLLATE pg_catalog."default",
CONSTRAINT parent_pkey PRIMARY KEY (parent_id)
)WITH (
OIDS = FALSE
)
TABLESPACE pg_default;
CREATE TABLE public.child
(
child_id integer NOT NULL,
name character varying(255) COLLATE pg_catalog."default",
parent_id integer NOT NULL,
CONSTRAINT child_pkey PRIMARY KEY (child_id),
CONSTRAINT fk7dag1cncltpyhoc2mbwka356h FOREIGN KEY (parent_id)
REFERENCES public.parent (parent_id) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE NO ACTION
)
WITH (
OIDS = FALSE
)
TABLESPACE pg_default;
I'm getting error while persisting child record.
Error -
Hibernate:
insert
into
child
(name, child_id)
values
(?, ?)
2022-07-19 23:12:31.727 WARN 20940 --- [nio-8080-exec-2] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 0, SQLState: 23502
2022-07-19 23:12:31.727 ERROR 20940 --- [nio-8080-exec-2] o.h.engine.jdbc.spi.SqlExceptionHelper : ERROR: null value in column "parent_id" violates not-null constraint
Detail: Failing row contains (1, s1, null).
2022-07-19 23:12:31.728 INFO 20940 --- [nio-8080-exec-2] o.h.e.j.b.internal.AbstractBatchImpl : HHH000010: On release of batch it still contained JDBC statements
2022-07-19 23:12:31.754 ERROR 20940 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [parent_id]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement] with root cause
org.postgresql.util.PSQLException: ERROR: null value in column "parent_id" violates not-null constraint
Detail: Failing row contains (1, s1, null).
Not sure how hibernate will pick and assign the foreign key to child.
You have to set the bidirectional relationship first
public class Parent {
#Id
private Integer parentId;
private String name;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "parent", cascade = CascadeType.ALL)
private List<Child> children;
public void addChild(Child child) {
this.children.add(child);
child.setParent(this);
}
}
and add the children via that method.

Spring / Hibernate - StaleStateException thrown when deleting entity

One of my entities is throwing a StaleStateException when trying to delete it. Code in question:
#RestController
#RequestMapping("/cycles")
public class DeleteCycleController {
#DeleteMapping("{cycleId}")
#ResponseStatus(HttpStatus.NO_CONTENT)
public void deleteCycleById(#PathVariable("cycleId") UUID cycleId, Principal principal) {
// cycleRepository extends CrudRepository
cycleRepository.deleteById(new CycleId(cycleId));
// deleter.deleteCycle(new CycleId(cycleId));
}
}
Throws the following:
org.springframework.orm.ObjectOptimisticLockingFailureException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1; statement executed: HikariProxyPreparedStatement#716092925 wrapping delete from cycle where id='c4c1428e-c296-4199-85f6-8ef16e6999c9'::uuid; nested exception is org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1; statement executed: HikariProxyPreparedStatement#716092925 wrapping delete from cycle where id='c4c1428e-c296-4199-85f6-8ef16e6999c9'::uuid
Here are the hibernate logs just before the failure:
2021-03-11 20:34:11.532 DEBUG 55483 --- [nio-8080-exec-7] org.hibernate.SQL : requestId=b53dd96089f748cf942fc46867d32fb5, requestMethod=DELETE, correlationId=b53dd96089f748cf942fc46867d32fb5, requestURI=/cycles/c4c1428e-c296-4199-85f6-8ef16e6999c9, userId=5ae11e82-f8df-4fad-ae10-1aa57423ba31, orgId=c7389774-9afa-452b-aa1c-74e7b18bc04d : select cycle0_.id as id1_0_0_, cycle0_.attributes as attribut2_0_0_, cycle0_.created_at as created_3_0_0_, cycle0_.cycle_type_id as cycle_ty4_0_0_, cycle0_.description as descript5_0_0_, cycle0_.end_time as end_time6_0_0_, cycle0_.start_time as start_ti7_0_0_, cycle0_.end_location as end_loca8_0_0_, cycle0_.last_modified_at as last_mod9_0_0_, cycle0_.name as name10_0_0_, cycle0_.organization_id as organiz11_0_0_, cycle0_.start_location as start_l12_0_0_ from cycle cycle0_ where cycle0_.id=?
Hibernate: select cycle0_.id as id1_0_0_, cycle0_.attributes as attribut2_0_0_, cycle0_.created_at as created_3_0_0_, cycle0_.cycle_type_id as cycle_ty4_0_0_, cycle0_.description as descript5_0_0_, cycle0_.end_time as end_time6_0_0_, cycle0_.start_time as start_ti7_0_0_, cycle0_.end_location as end_loca8_0_0_, cycle0_.last_modified_at as last_mod9_0_0_, cycle0_.name as name10_0_0_, cycle0_.organization_id as organiz11_0_0_, cycle0_.start_location as start_l12_0_0_ from cycle cycle0_ where cycle0_.id=?
2021-03-11 20:34:11.533 TRACE 55483 --- [nio-8080-exec-7] o.h.type.descriptor.sql.BasicBinder : requestId=b53dd96089f748cf942fc46867d32fb5, requestMethod=DELETE, correlationId=b53dd96089f748cf942fc46867d32fb5, requestURI=/cycles/c4c1428e-c296-4199-85f6-8ef16e6999c9, userId=5ae11e82-f8df-4fad-ae10-1aa57423ba31, orgId=c7389774-9afa-452b-aa1c-74e7b18bc04d : binding parameter [1] as [OTHER] - [c4c1428e-c296-4199-85f6-8ef16e6999c9]
2021-03-11 20:34:11.542 DEBUG 55483 --- [nio-8080-exec-7] org.hibernate.SQL : requestId=b53dd96089f748cf942fc46867d32fb5, requestMethod=DELETE, correlationId=b53dd96089f748cf942fc46867d32fb5, requestURI=/cycles/c4c1428e-c296-4199-85f6-8ef16e6999c9, userId=5ae11e82-f8df-4fad-ae10-1aa57423ba31, orgId=c7389774-9afa-452b-aa1c-74e7b18bc04d : delete from cycle where id=?
Hibernate: delete from cycle where id=?
2021-03-11 20:34:11.542 TRACE 55483 --- [nio-8080-exec-7] o.h.type.descriptor.sql.BasicBinder : requestId=b53dd96089f748cf942fc46867d32fb5, requestMethod=DELETE, correlationId=b53dd96089f748cf942fc46867d32fb5, requestURI=/cycles/c4c1428e-c296-4199-85f6-8ef16e6999c9, userId=5ae11e82-f8df-4fad-ae10-1aa57423ba31, orgId=c7389774-9afa-452b-aa1c-74e7b18bc04d : binding parameter [1] as [OTHER] - [c4c1428e-c296-4199-85f6-8ef16e6999c9]
And the Cycle entity:
#javax.persistence.Entity
#Accessors(fluent = true)
#Getter
#NoArgsConstructor(access = AccessLevel.PRIVATE)
#Builder
#TypeDefs({#TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)})
public class Cycle {
#Id private UUID id;
private CycleName name;
private CycleDescription description;
private UUID cycleTypeId;
private UUID organizationId;
private Instant createdAt;
private Instant lastModifiedAt;
#Type(type = "jsonb")
private Map<String, Object> attributes;
private CycleDuration duration;
#Column(columnDefinition = "Geometry", nullable = true)
private Geometry startLocation;
private Geometry endLocation;
#OneToMany(mappedBy = "cycleId", cascade = CascadeType.ALL, orphanRemoval = false)
#Getter(AccessLevel.PRIVATE)
#Setter(AccessLevel.PUBLIC)
private List<CycleEntityMapping> entities = new ArrayList<>();
...
}
Any ideas as to what could be going wrong? Another (simpler) entity deletes fine.
Not sure if its the OneToMany causing issues, but I've tried changing the cascade type, orphan removal and fetch type with no luck. Otherwise, could it be caused by the value objects? Note that updating the entity works fine - it's only failing on delete.
In this case, it was caused by a bug in a before delete trigger. There was a bug in the trigger causing the row to not be deleted:
CREATE OR REPLACE FUNCTION trigger_delete_row_backup()
RETURNS trigger AS
$BODY$
BEGIN
INSERT INTO deleted_cycle values (OLD.*);
RETURN NEW;
-- should actually be RETURN OLD
END;
$BODY$
language PLPGSQL;
Once the trigger was fixed, the issue no was resolved.

Hibernate/JPA - one primary key parent to composite key child

Whats wrong in my jpa mapping, im trying to map the parent class with one primary key to the child class with composite key, but it seems its inserting in the wrong table, it already generate 2 table but unfortunately i didn't bind the foreign key(policy_value_summary_id)
#Entity
#Table(name = "POLICY_VALUE_SUMMARY")
public class PolicyValueSummary {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="POLICY_VALUE_SUMMARY_ID")
private Long policyValueSummaryId;
#MapsId("policyValueSummaryId")
#OneToMany
private Set<PolicyValue> policyValues;
}
the child class have composite keys with one is the parent id.
#Entity
#Table(name = "POLICY_VALUE")
public class PolicyValue {
#EmbeddedId
#AttributeOverrides({
#AttributeOverride(name = "policyValueSummaryId", column = #Column(name = "POLICY_VALUE_SUMMARY_ID")),
#AttributeOverride(name = "planAtrId", column = #Column(name = "PLAN_ATR_ID")) })
private PolicyValuePk policyValuePk;
}
This is my child class composite keys.
#Embeddable
public class PolicyValuePk implements Serializable {
private Long policyValueSummaryId;
private Long planAtrId;
}
Im trying to save the policy summary value(parent) with the policy value(child class) like this
PolicyValuePk pk = new PolicyValuePk();
pk.setPlanAtrId(Long.valueOf("1"));
Set<PolicyValue> policyValues = new HashSet<>();
policyValues.add(new PolicyValue(pk));
PolicyValueSummary summary = new PolicyValueSummary();
summary.setPolicyValues(policyValues);
repo.save(summary);
Here is the error that being output to me
Hibernate: select hibernate_sequence.nextval from dual
Hibernate: insert into policy_value_summary (policy_value_summary_id) values (?)
Hibernate: insert into policy_value_summary_policy_values (policy_value_summary_policy_value_summary_id, policy_values_plan_atr_id, policy_values_policy_value_summary_id) values (?, ?, ?)
WARN 6880 --- [ main] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 972, SQLState: 42000
ERROR 6880 --- [ main] o.h.engine.jdbc.spi.SqlExceptionHelper : ORA-00972: identifier is too long
No, prior to Oracle version 12.2, identifiers are not allowed to exceed 30 characters in length. See the document
http://docs.oracle.com/cd/B28359_01/server.111/b28286/sql_elements008.htm#SQLRF00223
But from from version 12.2 they can be up to 128 bytes long

Why bidirectional mapping fails with empty relationship

Following are my two related tables
public class VProduct{
#Id
#Column(name="product_id")
private Long productId;
#OneToMany(mappedBy="vProduct", fetch = FetchType.EAGER, cascade={CascadeType.REMOVE})
private Set<ProductPan> pans;
}
public class ProductPan {
#Id
#Column(name="product_pan_id")
private Long productPanId;
#Fetch(FetchMode.JOIN)
#ManyToOne(optional=true, fetch=FetchType.EAGER)
#JoinColumn(name="product_id", referencedColumnName = "product_id", insertable = false, updatable = false)
private VProduct vProduct;
}
I get the following exception when i try to query the VProduct tabel.
org.hibernate.exception.SQLGrammarException: ERROR: column pans0_.product_pan_id does not exist
What am i doing wrong here ? At the moment ProductPan table is empty. And its not guranteed to have any items for a VProduct. if thats the problem is there any annotation i can add to ignore that null data problem ?
This is the hibernate query and result
14:39:49,994 INFO [stdout] (http-localhost-127.0.0.1-8080-1) Hibernate: select pans0_.product_id as product3_101_1_, pans0_.product_pan_id as product1_1_, pans0_.product_pan_id as product1_71_0_, pans0_.pan_id as pan2_71_0_, pans0_.product_id as product3_71_0_ from product_pan pans0_ where pans0_.product_id=?
14:39:50,113 WARN [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (http-localhost-127.0.0.1-8080-1) SQL Error: 0, SQLState: 42703
14:39:50,116 ERROR [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (http-localhost-127.0.0.1-8080-1) ERROR: column pans0_.product_pan_id does not exist

Save in one to many mapping in hibernate in updating instead of inserting

I am trying to do a one-to-many mapping using hibernate to insert some info into the DB but every time data is getting updated in the table rather than inserting a new row
I have 2 entities: ReportMaster and Reportdetail. where many Reportdetail data contain the ID which is Foreign key mapped to report master primary key column Id
#Entity
#Table(name = "ReportMaster")
public class ReportMaster implements Serializable {
private Integer repId;
private Set<ReportDetail> reportDetails = new HashSet<ReportDetail>();
#Id
#GeneratedValue
#Column(name = "RepId", unique = true, nullable = false)
public Integer getRepId() {
return this.repId;
}
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "reportMaster")
public Set<ReportDetail> getReportDetails() {
return this.reportDetails;
}
2nd entity is:
#Entity
#Table(name = "ReportDetail")
public class ReportDetail implements Serializable {
private String repColumn;
private String colData;
//.......corresponding getters and setters
private ReportMaster reportMaster;
#ManyToOne(targetEntity = ReportMaster.class)
#JoinColumn(name = "RepId")
public ReportMaster getReportMaster() {
return this.reportMaster;
}
I want to insert a new row into the reportdetails table, but it is getting updated:
ReportMaster report=new ReportMaster(req.getReportName(), req.getCid(), req.getReportDesc(), new Date());
report.addDetail(new ReportDetail(repcol,desc);
getTemplate().save(obj);
The generated HQL is:
org.hibernate.SQL - insert into ReportMaster (CreateDate, CustomerID, RepDesc, ReportName) values (?, ?, ?, ?)
org.hibernate.SQL - update ReportDetail set RepId=? where ColData=? and RepColumn=?
2013-02-16 10:13:34,109[http-6060-1] ERROR org.hibernate.event.def.AbstractFlushingEventListener - Could not synchronize database state with session
org.hibernate.jdbc.BatchedTooManyRowsAffectedException: Batch update returned unexpected row count from update [0]; actual row count: 2; expected: 1
at org.hibernate.jdbc.Expectations$BasicExpectation.checkBatched(Expectations.java:71)
at org.hibernate.jdbc.Expectations$BasicExpectation.verifyOutcome(Expectations.java:46)
at org.hibernate.jdbc.NonBatchingBatcher.addToBatch(NonBatchingBatcher.java:24)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2403)
at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2307)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2607)
at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:92)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:250)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:234)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:142)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
You should set the property 'reportMaster' of ReportDetail like this:
ReportMaster report=new ReportMaster(req.getReportName(), req.getCid(),req.getReportDesc(), new Date());
// create detail and set its master
ReportDetail detail = new ReportDetail(repcol,desc)
detail.setReportMaster(report);
report.addDetail(detail);
getTemplate().save(obj);
Follow this document.
Hope this helps.

Categories

Resources