I´m writing a sample project for my personal blog about how to use Spring Boot from scratch. At this moment trying to save my entities on a H2 database, I am receiving this mapping exception from the class BulkController which is RestController class trying to save instances of my Document
POJO class.
Here is the code of GET
method using double brace initialization:
Iterable<Document> records = csvParser.getRecords()
.stream()
.skip(1)
.map(record -> new Document() {{
setSource(record.get(0));
setCodeListCode(record.get(1));
setCode(record.get(2));
setDisplayValue(record.get(3));
setLongDescription(record.get(4));
}})
.collect(Collectors.toList());
documentRepository.saveAll(records);
Checking the raised exception:
org.hibernate.MappingException: Unknown entity: com.josephrodriguez.learning.springboot.controller.BulkController$1
at org.hibernate.metamodel.internal.MetamodelImpl.entityPersister(MetamodelImpl.java:704) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
at org.hibernate.internal.SessionImpl.getEntityPersister(SessionImpl.java:1608) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:149) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:70) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:99) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
Some part of me felt some curiosity to check the class of Iterable items.
for (Document d: records) {
System.out.println(d.getClass());
}
As I suspected, this was the output:
class com.josephrodriguez.learning.springboot.controller.BulkController$1
Removing the use of map
function everything works fine.
Question: Why the map
function with the double brace initialization changes the class type of the expected items of the collection?
CodePudding user response:
new Document() {...}
is an anonymous class and since I suppose your code is executed in ...BulkController
it is called as ...BulkController$1
and hence is not recognized by Hibernate as a managed type. Doesn't matter whether it is new Document {}
or new Document {{}}
.
Implement an adequate constuctor/wither/builder/setter function for Document
class and everything should work just fine.
Eg. using lombok.Builder
:
@Builder
public class Document {...}
...
Iterable<Document> records = csvParser.getRecords()
.stream()
.skip(1)
.map(record ->
Document.builder()
.source(record.get(0))
.codeListCode(record.get(1))
.code(record.get(2))
.displayValue(record.get(3))
.longDescription(record.get(4))
.build()
)
.collect(Collectors.toList());
documentRepository.saveAll(records);
P.S. Idk how you made it work removing map
, but JpaRepository<Document, ID>
would always expect an Iterable<Document>
parameter.
CodePudding user response:
My answer : org.hibernate.MappingException: Unknown entity
exception occurs because persistence Context doesn't manage BulkController$1.
Like mention of Serg Vasylchak above, {{ }}
(double brace) creates an anoymous class derived outer class. ex. BulkController. But persistence context doesn't know about the type of Bulkcontroller.
So it works when you remove map
logic, because double brace initialization is located in map
. Why don't you create Document class through builder
recommended by Serg Vasylchark?