Hibernate mapping error while inserting child record - java

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.

Related

Spring JPA #OneToMany Parameter value [] did not match expected type

I get this error when requesting service line:
List<Order> orders = ordersRepository.getByCustomerId(id);
Error:
org.springframework.dao.InvalidDataAccessApiUsageException: Parameter value [5] did not match expected type [nz.webshop.models.Customer.Customers (n/a)]; nested exception is java.lang.IllegalArgumentException: Parameter value [5] did not match expected type [nz.webshop.models.Customer.Customers (n/a)]
Repository:
public interface OrdersRepository extends JpaRepository<Order, Integer> {
List <Order> getByCustomerId(Integer customerId);
}
Entities:
#EntityA:
#Table(name = "orders")
public class Order {
#ManyToOne(targetEntity=Customers.class)
#JoinColumn (name = "customer_id", referencedColumnName="customer_id")
private Integer customerId;
...getters/setters
#EntityB:
#Table (name ="customer")
public class Customers {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name = "customer_id")
private Integer customerId;
#OneToMany(targetEntity = Order.class, mappedBy = "customerId")
private List<Order> Order;
...getters/setters
Where tables are like this:
CREATE TABLE orders
(
order_id INT AUTO_INCREMENT PRIMARY KEY,
customer_id INT,
FOREIGN KEY (customer_id) REFERENCES customer (customer_id)
);
CREATE TABLE customer
(
customer_id INT AUTO_INCREMENT PRIMARY KEY,
first_name VARCHAR(50) ,
last_name VARCHAR(50)
);
Update:
I changed EntityA as follows:
#EntityA:
#Table(name = "orders")
public class Order {
#Column(name = "customer_id")
private Integer customerId;
#ManyToOne(targetEntity=Customers.class)
private Customer customer;
...getters/setters
But then when requesting the same service line new error: org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet. Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'order0_.customer_customer_id' in 'field list'.
Where is the problem could be?
It looks like the Order.customerId property is not set up correctly. You're requesting that ManyToOne find Customer models based on their IDs, but then you're loading the models as Integers. Try this instead:
#ManyToOne
#JoinColumn(name = "customer_id", referencedColumnName="customer_id")
private Customer customer;
Let me know if this works, and if not, we can troubleshoot some more.

Jackson doesn't serialize properties of #EmbeddedId property

I'm making a Spring app with Hibernate and MySQL. One of my tables has a composite primary key consisting of two foreign keys and a timestamp. I have created the table like this:
CREATE TABLE `trustAssessments` (
`deviceId` int not null,
`tmsId` int not null,
`trustLevel` float not null,
`honesty` float not null,
`cooperativeness` float not null,
`communityInterest` float not null,
`tstamp` timestamp not null,
primary key (`tmsId`, `deviceId`, `tstamp`),
key `FK_PEERTMS_idx` (`tmsId`),
constraint `FK_PEERTMS`
foreign key (`tmsId`)
references `peerTMS` (`id`)
on delete no action on update no action,
key `FK_TRUSTED_DEVICE_idx` (`deviceId`),
constraint `FK_TRUSTED_DEVICE`
foreign key (`deviceId`)
references `device` (`id`)
on delete no action on update no action
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;
The corresponding Entity:
#Entity
#Table(name="trustassessments")
#JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class,
property = "id")
public class TrustAssessment {
#EmbeddedId
#JsonView(Views.Public.class)
//#JsonUnwrapped
private TrustAssessmentId id;
#Column(name="trustLevel")
#JsonView(Views.Public.class)
private float trustLevel;
#Column(name="honesty")
#JsonView(Views.Public.class)
private float honesty;
#Column(name="cooperativeness")
#JsonView(Views.Public.class)
private float cooperativeness;
#Column(name="communityInterest")
#JsonView(Views.Public.class)
private float communityInterest;
#ManyToOne(cascade={CascadeType.PERSIST, CascadeType.DETACH, CascadeType.MERGE, CascadeType.REFRESH})
#JoinColumn(name="deviceId")
#MapsId("deviceId")
#JsonView(Views.Internal.class)
private Device device;
#ManyToOne(cascade= {CascadeType.PERSIST, CascadeType.DETACH, CascadeType.MERGE, CascadeType.REFRESH})
#JoinColumn(name="tmsId")
#MapsId("tmsId")
#JsonView(Views.Internal.class)
private PeerTms peerTms;
....
And the TrustAssessmentId embeddable class which defines the composite key:
#Embeddable
public class TrustAssessmentId implements Serializable {
#Column(name="deviceId")
int deviceId;
#Column(name="tmsId")
int tmsId;
#Column(name="tstamp", updatable=false, columnDefinition="TIMESTAMP")
#Temporal(javax.persistence.TemporalType.TIMESTAMP)
#JsonSerialize(as = Date.class)
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
private Date tstamp = new Date();
....
I have two problems:
Problem 1: The first problem is that, when I use POST to create a new TrustAssessment, it is persisted, but the id value in the json in the response body is empty. I have checked with the debugger that the properties are not null.
For example, if I POST this:
{
"id": {
"deviceId": 21,
"tmsId": 20
},
"trustLevel": 0.4,
"honesty": 0.6,
"cooperativeness": 0.4,
"communityInterest": 0.2
}
I get this in the response body:
{
"id": {},
"trustLevel": 0.4,
"honesty": 0.6,
"cooperativeness": 0.4,
"communityInterest": 0.2
}
I can see in MySQL Workbench that it is persisted:
Problem 2: When I try to do a GET request to retrieve the persisted entity with this request body :
{
"id": {
"deviceId": 21,
"tmsId": 20,
"tstamp": "2019-11-29 19:20:21"
}
}
I get an empty response body, which means it can't find it. This also applies with DEL request which throws:
SEVERE: Servlet.service() for servlet [dispatcher] in context with
path [/tms-rest-again] threw exception [Request processing failed;
nested exception is java.lang.IllegalArgumentException: attempt to
create delete event with null entity] with root cause
java.lang.IllegalArgumentException: attempt to create delete event
with null entity at
org.hibernate.event.spi.DeleteEvent.(DeleteEvent.java:31) at
org.hibernate.internal.SessionImpl.delete(SessionImpl.java:951) at
com.cybertrust.tms.dao.TrustAssessmentDAOImpl.deleteTrustAssessment(TrustAssessmentDAOImpl.java:58)
at
com.cybertrust.tms.service.TmsServiceImpl.deleteTrustAssessment(TmsServiceImpl.java:202)
....

JPA update record is failing due to #OneToMany

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<>();

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

Hibernate constraint fails on cascade save

I have problem with cascade save of related entities. My UserEntity is related "one to many" with RegistrationTokenEntity. When I try to save this entities cascaded I get exception. Here is code:
UserEntity:
#Entity
#Table(name = "user", schema = "", catalog = "myDatabase")
public class UserEntity {
private int userId;
private String login;
// Some other fields
private Set<RegistrationTokenEntity> registrationTokenEntities = new HashSet<RegistrationTokenEntity>(0);
#OneToMany(fetch = FetchType.LAZY, mappedBy = "userId", cascade = CascadeType.ALL)
public Set<RegistrationTokenEntity> getRegistrationTokenEntities() {
return registrationTokenEntities;
}
public void setRegistrationTokenEntities(Set<RegistrationTokenEntity> registrationTokenEntities) {
this.registrationTokenEntities = registrationTokenEntities;
}
#Id
#Column(name = "user_id")
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
// Some other setters and getters
}
RegistrationTokenEntity:
#Entity
#Table(name = "registration_token", schema = "", catalog = "myDatabase")
public class RegistrationTokenEntity {
private int registrationTokenId;
private UserEntity userId;
// Some other fields
#Id
#Column(name = "registration_token_id")
public int getRegistrationTokenId() {
return registrationTokenId;
}
public void setRegistrationTokenId(int registrationTokenId) {
this.registrationTokenId = registrationTokenId;
}
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "user_id", nullable = false)
public UserEntity getUserId() {
return userId;
}
public void setUserId(UserEntity userId) {
this.userId = userId;
}
// Some others setters and getters
}
Here is how I save:
private void addNewUser(SignupForm homepageForm, PasswordEncoder passwordEncoder) {
UserEntity userEntity = new UserEntity(homepageForm);
RegistrationTokenEntity registrationTokenEntity = new RegistrationTokenEntity();
registrationTokenEntity.setConfirmed((byte)0);
UUID token = UUID.randomUUID();
registrationTokenEntity.setToken(token.toString());
registrationTokenEntity.setUserId(userEntity);
userEntity.getRegistrationTokenEntities().add(registrationTokenEntity);
userRepository.saveAndFlush(userEntity);
}
Here is my database SQL related to user and registerToken tables:
CREATE TABLE IF NOT EXISTS `myDatabase`.`user` (
`user_id` INT NOT NULL AUTO_INCREMENT,
`login` VARCHAR(30) NOT NULL,
// Some other fields
PRIMARY KEY (`user_id`),
UNIQUE INDEX `login_UNIQUE` (`login` ASC),
UNIQUE INDEX `username_UNIQUE` (`username` ASC),
UNIQUE INDEX `email_UNIQUE` (`email` ASC))
ENGINE = InnoDB;
CREATE TABLE IF NOT EXISTS `myDatabase`.`registration_token` (
`registration_token_id` INT NOT NULL AUTO_INCREMENT,
`user_id` INT NOT NULL,
// Some other fields
PRIMARY KEY (`registration_token_id`, `user_id`),
INDEX `fk_registration_token_user1_idx` (`user_id` ASC),
CONSTRAINT `fk_registration_token_user1`
FOREIGN KEY (`user_id`)
REFERENCES `myDatabase`.`user` (`user_id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
On output I get:
07-Jun-2015 21:07:25.257 WARN [http-apr-8080-exec-38] org.hibernate.engine.jdbc.spi.SqlExceptionHelper.logExceptions SQL Error: 1452, SQLState: 23000
07-Jun-2015 21:07:25.257 ERROR [http-apr-8080-exec-38] org.hibernate.engine.jdbc.spi.SqlExceptionHelper.logExceptions Cannot add or update a child row: a foreign key constraint fails (`myDatabase`.`registration_token`, CONSTRAINT `fk_registration_token_user1` FOREIGN KEY (`user_id`) REFERENCES `user` (`user_id`) ON DELETE NO ACTION ON UPDATE NO ACTION)
07-Jun-2015 21:07:25.260 INFO [http-apr-8080-exec-38] org.hibernate.engine.jdbc.batch.internal.AbstractBatchImpl.release HHH000010: On release of batch it still contained JDBC statements
07-Jun-2015 21:07:25.262 WARN [http-apr-8080-exec-38] org.hibernate.engine.jdbc.spi.SqlExceptionHelper$StandardWarningHandler.logWarning SQL Warning Code: 1452, SQLState: 23000
07-Jun-2015 21:07:25.262 WARN [http-apr-8080-exec-38] org.hibernate.engine.jdbc.spi.SqlExceptionHelper$StandardWarningHandler.logWarning Cannot add or update a child row: a foreign key constraint fails (`myDatabase`.`registration_token`, CONSTRAINT `fk_registration_token_user1` FOREIGN KEY (`user_id`) REFERENCES `user` (`user_id`) ON DELETE NO ACTION ON UPDATE NO ACTION)
And here is root exceptions stack:
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
org.hibernate.exception.ConstraintViolationException: could not execute statement
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (`myDatabase`.`registration_token`, CONSTRAINT `fk_registration_token_user1` FOREIGN KEY (`user_id`) REFERENCES `user` (`user_id`) ON DELETE NO ACTION ON UPDATE NO ACTION)
Have you any idea what I'm doing wrong?
I got this!
I had to add generated value strategy to my #Id like this:
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "user_id")
public int getUserId() {
return userId;
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "registration_token_id")
public int getRegistrationTokenId() {
return registrationTokenId;
}

Categories

Resources