I'm developing a Backend app using jpa and springboot (this is my first time) using postgreSQL as Databse.
That's my "Restaurant Entity class", which has as Primary key "id_ristorante"
#Entity
#Table(name = "ristorante")
#JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id_ristorante")
public class Ristorante implements Serializable{
//Primary key
#Id
#Column(name = "id_ristorante")
private Integer id_ristorante;
//Constructors
public Ristorante() {
}
I get This error from spring when I try to get any information from DB using this Entity
2023-02-13T18:58:01.735+01:00 WARN 6304 --- [nio-8080-exec-1] .c.j.MappingJackson2HttpMessageConverter : Failed to evaluate Jackson serialization for type [class com.ingsw.server.ratatouille23.Models.Entities.Ristorante]: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Invalid Object Id definition for com.ingsw.server.ratatouille23.Models.Entities.Ristorante: cannot find property with name 'id_ristorante' 2023-02-13T18:58:01.742+01:00 WARN 6304 --- [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpMediaTypeNotAcceptableException: No acceptable representation]
Does anyone knows how to solve it? I have another entity class and had no problem with that.
If i add #JsonManagedReference under #Column it works but it doesn't make any sense to me.
Related
From my previous question Hibernate: can save the object, but cannot load it back, I had the model class (entity) as this:
#Entity
#Data
#Table(name = "UserDetails")
public class User {
#Id
private int id;
private String name;
#ElementCollection
private Collection<Address> addresses = new ArrayList<>();
}
Now the collection addresses has annotation #ElementCollection from jpa which uses this information to create another table with each for for each element in that collection. Now the way the hibernate fetches these element back has 2 different ways: fetch = FetchType.EAGER | FetchType.LAZY. The lazy way, is the default one. Now when I (as in my previous question) didn't specify the fetch type (which defaults to LAZY way), I got
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
Application context error (which doesn't help to diagnose the issue, btw). However after changing the fetch type to EAGER, no error happened. So the question is why (why cannot the hibernate handle the default-lazy way) ?
I am trying to create a handler method in controller class in spring boot to handle post request coming with json in body. I am trying to deserialize this incoming json to object of a class using #RequestBody attribute in spring boot and then trying to save it in my database.
I have used #manytomany bidirectional relationship between Account and Customer class.
Account.java
#Entity
#Table(name = "Account")
public class Account {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
public int accountNumber;
public String accountType;
public int balance;
#ManyToMany(cascade = CascadeType.ALL)
#JsonManagedReference
private List<Customer> customers;
}
//skipped setters and getters and constructor
Customer.java
#Entity
#Table(name = "Customer")
public class Customer {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
public int customerId;
public String firstName;
public String lastName;
public String email;
#ManyToMany(mappedBy = "customers")
#JsonBackReference
private List<Account> accounts;
//skipped constructors , getters and setters.
}
Handler method in controller class
// post method to add record in account table
#PostMapping("/accounts")
public ResponseEntity<Account> postAccount(#RequestBody Account account) {
System.out.println(account);//trying to print incoming account class object
Account ac = this.accountServices.addAccount(account);
return new ResponseEntity<>(ac, HttpStatus.OK);
}
Postrequest in Postman
Error on console is
I have started !!!!
2021-08-03 22:52:37.011 INFO 17508 --- [nio-8081-exec-2] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2021-08-03 22:52:37.012 INFO 17508 --- [nio-8081-exec-2] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2021-08-03 22:52:37.015 INFO 17508 --- [nio-8081-exec-2] o.s.web.servlet.DispatcherServlet : Completed initialization in 2 ms
2021-08-03 22:52:37.021 WARN 17508 --- [nio-8081-exec-2] .c.j.MappingJackson2HttpMessageConverter : Failed to evaluate Jackson deserialization for type [[simple type, class ma20099449.foundation.bank.ma20099449_bank.Entities.Account]]: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot handle managed/back reference 'defaultReference': back reference type (`java.util.List<ma20099449.foundation.bank.ma20099449_bank.Entities.Account>`) not compatible with managed type (ma20099449.foundation.bank.ma20099449_bank.Entities.Account)
2021-08-03 22:52:37.029 WARN 17508 --- [nio-8081-exec-2] .c.j.MappingJackson2HttpMessageConverter : Failed to evaluate Jackson deserialization for type [[simple type, class ma20099449.foundation.bank.ma20099449_bank.Entities.Account]]: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot handle managed/back reference 'defaultReference': back reference type (`java.util.List<ma20099449.foundation.bank.ma20099449_bank.Entities.Account>`) not compatible with managed type (ma20099449.foundation.bank.ma20099449_bank.Entities.Account)
2021-08-03 22:52:37.031 WARN 17508 --- [nio-8081-exec-2] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/json;charset=UTF-8' not supported]
There is some problem for deserializing the incoming json to Account class object but I don't know the error.
Someone please help me with code.
Based on that issue, you can't use your
#JsonManagedReference and #JsonBackReference in with #ManyToMany relationship.
You have many other alternatives:
for general-purpose handling of (possibly) cyclic dependencies, #JsonIdentityInfo may be used,
you can also use the #JsonIgnore annotation on your accounts list in Customer class,
another solution is to use dedicated Data Transport Objects (DTOs) to transfer JSONs. Here is interesting discussion, when you should use it and when shouldn't,
However, first of all I would consider if you really need a many-to-many relationship - in most cases a one-to-many relationship or a unidirectional relationship is enought, which will greatly simplify mapping.
First of all I think that you don't need to include your ID into the POST request in Postman, because it is generated by Hibernate in your database.
And for the other hand, try to delte any #JsonManagedReference
In java Spring and under MongoDB i am creating the following field (id) of a class :
#Id
public String _id;
in order to create the identifier field with the name _id but i get an indentifier id with the compilation warning : WARN 11916 --- [ main] o.s.d.m.c.m.BasicMongoPersistentProperty : Customizing field name for id property not allowed! Custom name will not be considered!
My Question is how to change the name of the id field in java spring (if that's even possible)
EDIT : i tried with #Field("_id") but it's not working.
Thank you,
TL;DR
The warning comes from MongoDB which is unhappy of an #Id field having a property name other than those supported by spring data based on the root cause
Based of the supported Id fields names stored in the Set SUPPORTED_ID_PROPERTY_NAMES includes {"id", "_id}.
That being said your naming of id field should be accepted which is apparently not. It may come from another document. You should check how many #Document you have.
Usually, a basic mongoDB document in Spring includes two main information:
The #Document annotation in the model object (e.g a User)
The #Id annotation from the id property in the model class
Here an example :
#Document
public class User {
#Id
private BigInteger id;
// other fields
/**
* Returns the identifier of the document.
*
* #return the id
*/
public BigInteger getId() {
return id;
}
// getters & setters for other fields (id have only a getter /!\)
}
What you described in your question description is more convenient for JPA based entity for SQL-databases and not suitable for MongoDB document.
Also, I encourage you to check Spring Data MongoDB project and this sample project to see "best practice to start with" when creating such projects
I changed the FetchType of all my #ManyToOne to FetchType.LAZY from the default FetchType.EAGER.
So an entity looks like this for example:
#Data
#NoArgsConstructor
#Entity
#JsonInclude(JsonInclude.Include.NON_NULL)
public class DailyEntry {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
// more attributes
#ManyToOne(fetch = FetchType.LAZY)
private Project project;
#ManyToOne(fetch = FetchType.LAZY)
private Employee employee;
}
But im getting the following error, each time I do a request to get the entities:
ERROR 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) (through reference chain: java.util.ArrayList[0]->de.hiqs.dailyentry.DailyEntry["project"]->de.hiqs.project.Project$HibernateProxy$cmEQxiMb["customer"]->de.hiqs.customer.Customer$HibernateProxy$BV240DdJ["hibernateLazyInitializer"])
As the error states, i can disable SerializationFeature.FAIL_ON_EMPTY_BEANS and everything will work fine. But is that what I am supposed to do or what is the usual way to fix this issue?
To enable lazy loading in ToOne relationships Hibernate is putting a proxy instead of the the real object in the reference.
In order to serialize your bean you have to make sure that the references are initialized. For example by calling the getter or using EntityGraph:
https://thoughts-on-java.org/jpa-21-entity-graph-part-1-named-entity/
I am having some trouble figuring out why something is not working when trying to persist an object using Springs default Repositories. I am using hibernate as my persistence layer and Spring MVC framework. I use JPA instead of hibernate mapping files.
The error I am seeing is the following:
WARN : org.hibernate.util.JDBCExceptionReporter - SQL Error: 1366, SQLState: HY000
ERROR: org.hibernate.util.JDBCExceptionReporter - Incorrect integer value: '\xAC\xED\x00\x05sr\x00!com.kwhours.butternut.domain.Type\xCF;\xBF\xEF\x8A\x82\x87\xF1\x02\x00\x0DZ\x00\x06isLeafI\x00\x05levelL\' for column 'type_id' at row 1
I am trying to persist a domain object with JPA annotations the relevant part of that code is:
#Entity
#Table(name = "question")
public class Question implements java.io.Serializable {
private Type type;
#Column(name = "type_id")
public Type getType() {
return this.type;
}
public void setType(Type type) {
this.type = type;
}
}
I have a foreign key constraint properly set up on the question.type_id column to type.id column. I am able to have my objects all properly represented in code but when I try to make the following repository persist the object, I get the afore mentioned error.
public interface QuestionRepository extends CrudRepository<Question, Long> {
public List<Question> findByDatasetInstanceId(Long datasetInstanceId);
}
So to be clear. I can make a new question object and retrieve a type object from the db using a repository. I can set questions.type to this new type object but I get that error whenever I try to persist the question which contains that type using the repository above. I checked out the type object in the debugger and there seems to be nothing amiss with it. Any clues or suggestions are helpful. That looks like some kind of escape character sequence but I am not really sure.
So I was really silly about this. I am missing the proper annotations and it wasn't taking the type id out to insert but rather tryign to somehow insert this java object
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "type_id")
public Type getType() {
return this.type;
}
that code above solved the issue