I am working on a spring boot app where I am using JPA for all data transactions and I came across this error while using OneToMany relationship.
Here are both my models:
user.java
#Entity
public class user {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String username;
private String password;
private String role;
#ManyToOne(cascade=CascadeType.ALL)
private file f;
#JsonIgnore
#OneToMany(targetEntity=job.class,cascade=CascadeType.ALL)
private List<job> applied;
//getters ,setters and constuctors.
}
job.java
#Entity
public class job {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String role;
private String company;
private String salary;
private String description;
private String level;
private Date expiry;
private String skills;
private String location;
#JsonIgnore
#OneToMany(targetEntity=user.class,cascade=CascadeType.ALL)
private List<user> candidates;
//getters setters and constructor
}
here's the method that triggers the error:
public String applyToJob(Integer userId,Integer jobId)
{
job jobToApply= jobRepo.getOne(jobId);
user applier=userRepo.getById(userId);
List<job> jobs=applier.getApplied();
jobs.add(jobToApply);
applier.setApplied(jobs);
userRepo.save(applier);
List<user> candidates=jobToApply.getCandidates();
System.out.println(candidates);
candidates.add(userRepo.getOne(userId));
System.out.println(candidates);
jobToApply.setCandidates(candidates);
jobRepo.save(jobToApply);
return "Job Apply Success";
}
Now that I want to add data inside job's candidates field I get the below error:
2021-10-07 17:17:37.542 WARN 21696 --- [nio-8090-exec-4] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 1062, SQLState: 23000
2021-10-07 17:17:37.543 ERROR 21696 --- [nio-8090-exec-4] o.h.engine.jdbc.spi.SqlExceptionHelper : Duplicate entry '2' for key 'job_candidates.UK_q0o76ghxl59c5ip3qwatsxo3f'
2021-10-07 17:17:37.543 INFO 21696 --- [nio-8090-exec-4] o.h.e.j.b.internal.AbstractBatchImpl : HHH000010: On release of batch it still contained JDBC statements
2021-10-07 17:17:37.564 ERROR 21696 --- [nio-8090-exec-4] 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 [job_candidates.UK_q0o76ghxl59c5ip3qwatsxo3f]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement] with root cause
java.sql.SQLIntegrityConstraintViolationException: Duplicate entry '2' for key 'job_candidates.UK_q0o76ghxl59c5ip3qwatsxo3f'
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:117) ~[mysql-connector-java-8.0.26.jar:8.0.26]
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122) ~[mysql-connector-java
Seems like you are adding a candidate to the job entity, which is already previously mapped to that particular job.
Please thoroughly check your entries in the DB and try to find out if there is any candidate that is being added multiple times to the same job, preferably with id as 2.
Let me know if you face any further difficulties!
Related
I am building a REST-like API using Spring. I have encountered a problem in which using FetchType.LAZY along a #ManyToOne relationship causes an error when retrieving an entity using a JPA Repository.
Here’s a simplified, compilable version of my code:
A.java:
#Entity
public class A {
#Id
#GeneratedValue
private Long id;
#ManyToOne(fetch = FetchType.LAZY)
private B b;
public Long getId() {
return id;
}
public B getB() {
return b;
}
}
B.java:
#Entity
public class B {
#Id
#GeneratedValue
private Long id;
private String someData;
public Long getId() {
return id;
}
public String getSomeData() {
return someData;
}
}
ARepository.java:
#Repository
public interface ARepository extends JpaRepository<A, Long> {}
AController.java:
#RestController
#RequestMapping("a")
public class AController {
private final ARepository repository;
AController(ARepository repository) {
this.repository = repository;
}
#GetMapping("{id}")
A one(#PathVariable Long id) {
return repository.findById(id).orElse(null);
}
}
data-h2.sql:
INSERT INTO B (id, some_data) VALUES (1, 'Very large data I do not want to load unless explicitly requested');
INSERT INTO A (id, b_id) VALUES (1, 1);
I call the endpoint with curl -v http://localhost:8080/a/1 (Windows CMD)
Response expected: {"id": 1}
Response received instead: 500 Internal Server Error
Server console error:
ERROR 8484 --- [nio-8080-exec-9] 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.http.converter.HttpMessageConversionException: Type definition error: [simple type, class org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS)
If I remove fetch = FetchType.LAZY the call returns successfully, but the JSON includes all data from B, which is what I am trying to avoid.
I have 2 entities with unidirectional association.
#Entity
#Table(name = "albums")
public class Album {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String ownerId;
private String name;
private Boolean isPublic;
#OneToMany(orphanRemoval = true)
#JoinTable(
name = "album_album_cards",
joinColumns = #JoinColumn(name = "album_id"),
inverseJoinColumns = #JoinColumn(name = "album_card_id"))
private List<AlbumCard> cards;
}
#Entity
#Table(name = "album_cards")
public class AlbumCard {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private Integer price;
private String condition;
private String design;
private Integer count;
private Long cardId;
#UpdateTimestamp
private LocalDate updated;
}
And three tables albums, album_cards and album_album_cards (for mapping)
When i map entity to model the exception is throws.
2022-11-14 21:37:57.725 ERROR 18696 --- [nio-9999-exec-7] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet] with root cause
org.postgresql.util.PSQLException: ERROR: column "cards0_.album_id" must appear in the GROUP BY clause or be used in an aggregate function
at ru.berserkdeck.albums.impl.mapper.AlbumMapper.albumCardListToAlbumPositionModelList(AlbumMapper.java:57) ~[classes/:na]
at ru.berserkdeck.albums.impl.mapper.AlbumMapper.toModel(AlbumMapper.java:31) ~[classes/:na]
at java.base/java.util.Optional.map(Optional.java:260) ~[na:na]
at ru.berserkdeck.albums.impl.service.AlbumServiceImpl.getAlbum(AlbumServiceImpl.java:50) ~[classes/:na]
Last sql logs is
Hibernate: select album0_.id as id1_1_, album0_.is_public as is_publi2_1_, album0_.name as name3_1_, album0_.owner_id as owner_id4_1_ from albums album0_ where album0_.owner_id=? and album0_.id=?
Hibernate: select cards0_.album_id as album_id8_0_0_, cards0_.id as id1_0_0_, cards0_.id as id1_0_1_, cards0_.card_id as card_id2_0_1_, cards0_.condition as conditio3_0_1_, cards0_.count as count4_0_1_, cards0_.design as design5_0_1_, cards0_.price as price6_0_1_, cards0_.updated as updated7_0_1_ from album_cards cards0_ where cards0_.album_id=?
mapper code:
51 protected List<AlbumPositionModel> albumCardListToAlbumPositionModelList(List<AlbumCard> list) {
52 if (list == null) {
53 return new ArrayList<>();
54 }
55
56 List<AlbumPositionModel> list1 = new ArrayList<>();
57 list.forEach(e -> list1.add(albumCardToAlbumPositionModel(e))); <---- exception throws there. And it throws if i call any method of list (List<AlbumCard>)
58 return list1;
the service method, calling the mapper(i tried with Transactional annotation and without, result the same):
#Override
public Optional<AlbumModel> getAlbum(String ownerId, Long albumId) {
if (ownerId != null) {
return albumRepo
.findByOwnerIdAndId(ownerId, albumId)
.map(mapper::toModel);
} else {
return albumRepo
.findByIdAndIsPublic(albumId, true)
.map(mapper::toModel);
}
}
Anyone could help me? What I'm dooing wrong?
Try renaming the count column from
private Integer count;
to
#Column(name = "CARD_COUNT")
private Integer count;
in my Spring Boot application I'm trying to save an Entity with a few nested Entities that have a one-to-many relationship. I'm using JPA and Hibernate to save them to a MySQL database.
On the primary keys, I am using #GeneratedValue(strategy = GenerationType.AUTO) on a Long to automatically create values for new entities. This worked for some time, however recently I'm getting an error when trying to save the entity:
java.sql.SQLIntegrityConstraintViolationException: Duplicate entry '282' for key 'PRIMARY'
This is what my entities look like:
Question.java
#Entity
#Table(name = "question")
public class Question {
private Long id;
private List<Answer> answers;
// other fields
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
#OneToMany(mappedBy = "question", cascade = CascadeType.ALL, orphanRemoval = true)
public List<Answer> getAnswers() { return answers; }
public void setAnswers(List<Answer> answers) { this.answers = answers; }
}
Answer.java
#Entity
#Table(name = "answer")
public class Answer {
private Long id;
private Question question;
// other fields
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
#ManyToOne
#JoinColumn(name = "question_id")
public Question getQuestion() { return question; }
public void setQuestion(Question question) { this.question = question; }
}
Repositories are simply:
public interface QuestionRepository extends JpaRepository<Question, Long>{ ... }
Now let's say I am adding a new Question via a web form, including 4 Answers. When calling the repository simply like:
questionRepository.save(question);
After some investigation, it appears that Hibernate is using the auto increment value from the question table for the answers entities, which doesn't work because it already exist.
Trace output log:
Hibernate: insert into question (id) values (?)
2019-08-31 18:47:49.652 TRACE 11516 --- [nio-8080-exec-6] o.h.type.descriptor.sql.BasicBinder : binding parameter [6] as [BIGINT] - [281]
Hibernate: insert into answer (question_id, id) values (?, ?)
2019-08-31 18:47:49.688 TRACE 11516 --- [nio-8080-exec-6] o.h.type.descriptor.sql.BasicBinder : binding parameter [3] as [BIGINT] - [281]
2019-08-31 18:47:49.688 TRACE 11516 --- [nio-8080-exec-6] o.h.type.descriptor.sql.BasicBinder : binding parameter [4] as [BIGINT] - [282]
2019-08-31 18:47:49.746 WARN 11516 --- [nio-8080-exec-6] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 1062, SQLState: 23000
2019-08-31 18:47:49.746 ERROR 11516 --- [nio-8080-exec-6] o.h.engine.jdbc.spi.SqlExceptionHelper : Duplicate entry '282' for key 'PRIMARY'
2019-08-31 18:47:49.748 ERROR 11516 --- [nio-8080-exec-6] o.h.i.ExceptionMapperStandardImpl : HHH000346: Error during managed flush [org.hibernate.exception.ConstraintViolationException: could not execute statement]
2019-08-31 18:47:49.847 ERROR 11516 --- [nio-8080-exec-6] 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 [PRIMARY]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement] with root cause
java.sql.SQLIntegrityConstraintViolationException: Duplicate entry '282' for key 'PRIMARY'
I've verified that the auto_increment value on the answer table is 581.
What could be the cause of this? Is there property/configuration I'm missing?
Since MySQL doesn't support sequences natively so this issue might occur when #GeneratedValue(strategy = GenerationType.AUTO) is used.
Use the below workaround for id generation.
#Id
#GeneratedValue(
strategy= GenerationType.AUTO,
generator="native"
)
#GenericGenerator(
name = "native",
strategy = "native"
)
Please refer https://hibernate.atlassian.net/browse/HHH-11014 for further details.
You can also refer ::: https://vladmihalcea.com/why-should-not-use-the-auto-jpa-generationtype-with-mysql-and-hibernate/
very new to Java/Spring/Hibernate stack. I can't get the data extracted from and xlsx sheet using the apache poi to save to an mssql database. Using an in memory database, Derby, this all just works fine which leads me to believe that it has some thing to do with the data being mapped between the java class and the mssql database table.
DB:
CREATE TABLE BASICS.IncomingData.BulkRefundUpload (
id int PRIMARY KEY,
daxPaymentReference varchar(255),
amount float,
refundReason varchar(255),
invoiceId varchar(255),
processingStatus varchar(255),
retryCount int,
iglobisRequest varchar(255),
iglobisResponse varchar(255),
refundStatus varchar(255),
createDateTime date,
createdBy varchar(255),
updateDateTime date,
modifiedBy varchar(255)
)
Class:
// omitted imports
#Entity
#Table(name = "IncomingData.BulkRefundUpload")
public class Refund {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id", updatable = false, nullable = false)
private int id;
#Column
private String daxPaymentReference;
#Column
private double amount;
#Column
private String refundReason;
#Column
private String invoiceId;
#Column
private String processingStatus;
#Column
private int retryCount;
#Column
private String iglobisRequest;
#Column
private String iglobisResponse;
#Column
private String refundStatus;
#Column
#CreationTimestamp
private Date createDateTime;
#Column
private String createdBy;
#Column
#UpdateTimestamp
private Date updateDateTime;
#Column
private String modifiedBy;
// no arg constructor
public Refund() {}
// regular constructor
public Refund(String daxPaymentReference, double amount, String refundReason, String invoiceId, String processingStatus, int retryCount, String iglobisRequest, String iglobisResponse, String refundStatus, String createdBy, String modifiedBy) {
super();
this.daxPaymentReference = daxPaymentReference;
this.amount = amount;
this.refundReason = refundReason;
this.invoiceId = invoiceId;
this.processingStatus = processingStatus;
this.retryCount = retryCount;
this.iglobisRequest = iglobisRequest;
this.iglobisResponse = iglobisResponse;
this.refundStatus = refundStatus;
this.createdBy = createdBy;
this.modifiedBy = modifiedBy;
}
// getters and setters omitted
}
And the method trying to write the data, it iterates through rows in an xlsx:
List<Refund> refunds = new ArrayList<>();
sheet.rowIterator().forEachRemaining(row -> {
if(row.getRowNum() != 0) {
refunds.add(new Refund(
row.getCell(0).getStringCellValue(), //daxPaymentReference
row.getCell(1).getNumericCellValue(), //amount
row.getCell(2).getStringCellValue(), //refundReason
"",
"new",
0,
"",
"",
"",
"defaultCreatedByUser",
""
));
}
});
And finally the error:
Hibernate: select next value for hibernate_sequence
2019-01-23 13:58:04.260 WARN 1544 --- [nio-8080-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 102, SQLState: S0001
2019-01-23 13:58:04.260 ERROR 1544 --- [nio-8080-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper : Incorrect syntax near 'hibernate_sequence'.
2019-01-23 13:58:04.315 ERROR 1544 --- [nio-8080-exec-1] 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.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet] with root cause
com.microsoft.sqlserver.jdbc.SQLServerException: Incorrect syntax near 'hibernate_sequence'.
Adding image from debugger showing the values being added to the refund object:
I have this error with my Spring Data/JPA project:
SQL Error: -206, SQLState: 42703
DB2 SQL Error: SQLCODE=-206, SQLSTATE=42703, SQLERRMC=MYDONNEE0_.MYCONNEX_IDCON, DRIVER=4.19.26
SQL Error: -727, SQLState: 56098
DB2 SQL Error: SQLCODE=-727, SQLSTATE=56098, SQLERRMC=2;-206;42703;MYDONNEE0_.MYCONNEX_IDCON, DRIVER=4.19.26
SQL Error: -727, SQLState: 56098
DB2 SQL Error: SQLCODE=-727, SQLSTATE=56098, SQLERRMC=2;-206;42703;MYDONNEE0_.MYCONNEX_IDCON, DRIVER=4.19.26
Enter: my.package.test.web.rest.errors.ExceptionTranslator.processRuntimeException() with argument[s] = [org.springframework.http.converter.HttpMessageNotWritableException: Could not write content: could not extract ResultSet (through reference chain: my.package.test.repository.entity.MYconnex["MYdonnees"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: could not extract ResultSet (through reference chain: my.package.test.repository.entity.MYconnex["MYdonnees"])]
Exit: my.package.test.web.rest.errors.ExceptionTranslator.processRuntimeException() with result = <500 Internal Server Error,my.package.test.web.rest.errors.ErrorDTO#70b511c1,{}>
I search, but i don't find a problem with my entity.
MYconnex :
#Entity
#NamedQuery(name="MYconnex.findAll", query="SELECT u FROM MYconnex u")
public class MYconnex implements Serializable {
private static final long serialVersionUID = 1L;
#Id
private long IDCON;
private String key;
private Timestamp dateconnex;
private String mel;
private int tel;
//bi-directional many-to-one association to MYdonnees
#OneToMany(mappedBy="MYconnex")
private List<MYdonnees> MYdonnees;
//Getter and setter
}
MYdonnees :
#Entity
#NamedQuery(name="MYdonnees.findAll", query="SELECT u FROM MYdonnees u")
#Table(name="MYdonnees")
public class MYdonnees implements Serializable {
private static final long serialVersionUID = 1L;
#Id
private long idata;
#Lob
#Column(name="\"DATA\"")
private String data;
//bi-directional many-to-one association to MYconnex
#ManyToOne
private MYconnex MYconnex;
public MYdonnees() {
}
//Getter and Setter
}
My CrudRepository :
public interface ADRESSRepository extends CrudRepository<ADRESS, Integer> {
}
The DataBase :
I think the problem come from the entity, but I can't find this problem.
You can't convert a bidirectional relation of an enitity to JSON. You get an endless loop try to add #JsonIgnore to break the loop on your bi-directional association
#ManyToOne
#JsonIgnore
private Udsaconnex udsaconnex;
#jsonsetter
public void setUdsaconnex(Udsaconnex udsaconnex){
this.udsaconnex = udsaconnex;
}
I had the same problem, here is what worked for me:
In the parent class:
#JsonIgnore // to break endless loop in bi-directional association
public List<Udsaconnex> getUdsadonnees() {
return udsadonnees;
}
In the child class:
#ManyToOne
#JoinColumn(name = "idconnex") // You must specify the join column.
private Udsaconnex udsaconnex;
These two changes will resolve your problem.