Search code examples
jpavaadinh2one-to-many

Vaadin example project having trouble with @OneToMany @ManyToOne


Here is my public example project which is simplified and reproduces the scenario I'm struggling with: https://github.com/sketchbook22/help

The machine I'm developing on is using java version

java --version
java 19.0.1 2022-10-18
Java(TM) SE Runtime Environment (build 19.0.1+10-21)
Java HotSpot(TM) 64-Bit Server VM (build 19.0.1+10-21, mixed mode, sharing)

I created this project from VaadinStart then modified it. I was able to get a @OneToOne mapping to work. (Yay!) I have not been able to get a bidirectional JPA @ManyToOne / @OneToMany mapping to work.

I would like SamplePerson to have 2 Bats The data is injected into the h2 database in data.sql like this

insert into ape(version, id, color) values (1, 1, 'apricot')
insert into bat(version, id, color, zooKeeper) values (1, 1, 'brown', 1)
insert into bat(version, id, color, zooKeeper) values (1, 1, 'blue', 1)
insert into sample_person(version, id, ape, bats, c, d, e) values (1, 1, 1, ARRAY [1, 2], 'c', 'd', 'e')

I have confirmed this syntax using Set<Integer> in a different project So I suspect the problem is with the bindings...

Bat.java

@JsonBackReference
@ManyToOne
@JoinColumn(name = "SAMPlE_PERSON_ID", referencedColumnName = "SAMPLE_PERSON_ID", nullable = false)
public SamplePerson getZooKeeper() {
    return zooKeeper;
}

SamplePerson.java

@JsonManagedReference
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "zooKeeper")
public Set<Bat> getBats() {
    return bats;
}

I get this output (with errors) I receive when compiling through cmd with the mvnw command

[INFO] Scanning for projects...
[INFO]
[INFO] -------------------< com.example.application:my-app >-------------------
[INFO] Building my-app 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] >>> spring-boot-maven-plugin:3.2.2:run (default-cli) > test-compile @ my-app >>>
[INFO]
[INFO] --- maven-resources-plugin:3.3.1:resources (default-resources) @ my-app ---
[INFO] Copying 1 resource from src\main\resources to target\classes
[INFO] Copying 4 resources from src\main\resources to target\classes
[INFO]
[INFO] --- vaadin-maven-plugin:24.3.3:prepare-frontend (default) @ my-app ---
[INFO] Reflections took 1094 ms to scan 157 urls, producing 8908 keys and 43974 values
[INFO] Copying frontend resources from jar files ...
[INFO] Visited 156 resources. Took 453 ms.
[INFO]
[INFO] --- maven-compiler-plugin:3.11.0:compile (default-compile) @ my-app ---
[INFO] Changes detected - recompiling the module! :source
[INFO] Compiling 21 source files with javac [debug release 17] to target\classes
[INFO]
[INFO] --- maven-resources-plugin:3.3.1:testResources (default-testResources) @ my-app ---
[INFO] skip non existing resourceDirectory C:\git\help\src\test\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.11.0:testCompile (default-testCompile) @ my-app ---
[INFO] No sources to compile
[INFO]
[INFO] <<< spring-boot-maven-plugin:3.2.2:run (default-cli) < test-compile @ my-app <<<
[INFO]
[INFO]
[INFO] --- spring-boot-maven-plugin:3.2.2:run (default-cli) @ my-app ---
[INFO] Attaching agents: []
  __  __            _
 |  \/  |_   _     / \   _ __  _ __
 | |\/| | | | |   / _ \ | '_ \| '_ \
 | |  | | |_| |  / ___ \| |_) | |_) |
 |_|  |_|\__, | /_/   \_\ .__/| .__/
         |___/          |_|   |_|

2024-02-05T14:15:57.193-05:00  INFO 17592 --- [  restartedMain] com.example.application.Application      : Starting Application using Java 19.0.1 with PID 17592 (C:\git\help\target\classes started by sketc in C:\git\help)
2024-02-05T14:15:57.197-05:00  INFO 17592 --- [  restartedMain] com.example.application.Application      : No active profile set, falling back to 1 default profile: "default"
2024-02-05T14:15:57.246-05:00  INFO 17592 --- [  restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable
2024-02-05T14:15:57.246-05:00  INFO 17592 --- [  restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG'
2024-02-05T14:15:57.915-05:00  INFO 17592 --- [  restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode.
2024-02-05T14:15:57.999-05:00  INFO 17592 --- [  restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 75 ms. Found 6 JPA repository interfaces.
2024-02-05T14:15:58.657-05:00  INFO 17592 --- [  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port 8080 (http)
2024-02-05T14:15:58.670-05:00  INFO 17592 --- [  restartedMain] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2024-02-05T14:15:58.670-05:00  INFO 17592 --- [  restartedMain] o.apache.catalina.core.StandardEngine    : Starting Servlet engine: [Apache Tomcat/10.1.18]
2024-02-05T14:15:58.748-05:00  INFO 17592 --- [  restartedMain] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2024-02-05T14:15:58.749-05:00  INFO 17592 --- [  restartedMain] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1499 ms
2024-02-05T14:15:58.792-05:00  INFO 17592 --- [  restartedMain] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2024-02-05T14:15:58.975-05:00  INFO 17592 --- [  restartedMain] com.zaxxer.hikari.pool.HikariPool        : HikariPool-1 - Added connection conn0: url=jdbc:h2:mem:8020749f-e483-45a6-b8aa-df9ec048ad3e user=SA
2024-02-05T14:15:58.977-05:00  INFO 17592 --- [  restartedMain] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2024-02-05T14:15:58.988-05:00  INFO 17592 --- [  restartedMain] o.s.b.a.h2.H2ConsoleAutoConfiguration    : H2 console available at '/h2-console'. Database available at 'jdbc:h2:mem:8020749f-e483-45a6-b8aa-df9ec048ad3e'
2024-02-05T14:15:59.900-05:00  INFO 17592 --- [  restartedMain] c.v.f.s.VaadinServletContextInitializer  : Search for subclasses and classes with annotations took 721 ms
2024-02-05T14:16:00.323-05:00  INFO 17592 --- [  restartedMain] c.v.b.d.startup.DevModeStartupListener   : Starting dev-mode updaters in C:\git\help folder.
2024-02-05T14:16:00.362-05:00  INFO 17592 --- [  restartedMain] c.v.f.s.f.s.FullDependenciesScanner      : Visited 107 classes. Took 24 ms.
2024-02-05T14:16:00.364-05:00  INFO 17592 --- [  restartedMain] c.v.f.s.frontend.BundleValidationUtil    : Checking if a development mode bundle build is needed
2024-02-05T14:16:00.694-05:00  INFO 17592 --- [  restartedMain] c.v.f.s.frontend.BundleValidationUtil    : A development mode bundle build is not needed
2024-02-05T14:16:00.731-05:00  INFO 17592 --- [onPool-worker-1] c.v.f.s.frontend.TaskCopyFrontendFiles   : Copying frontend resources from jar files ...
2024-02-05T14:16:00.859-05:00  INFO 17592 --- [  restartedMain] o.hibernate.jpa.internal.util.LogHelper  : HHH000204: Processing PersistenceUnitInfo [name: default]
2024-02-05T14:16:00.926-05:00  INFO 17592 --- [  restartedMain] org.hibernate.Version                    : HHH000412: Hibernate ORM core version 6.4.1.Final
2024-02-05T14:16:00.964-05:00  INFO 17592 --- [  restartedMain] o.h.c.internal.RegionFactoryInitiator    : HHH000026: Second-level cache disabled
2024-02-05T14:16:01.066-05:00  INFO 17592 --- [onPool-worker-1] c.v.f.s.frontend.TaskCopyFrontendFiles   : Visited 21 resources. Took 335 ms.
2024-02-05T14:16:01.221-05:00  INFO 17592 --- [  restartedMain] o.s.o.j.p.SpringPersistenceUnitInfo      : No LoadTimeWeaver setup: ignoring JPA class transformer
2024-02-05T14:16:01.491-05:00 ERROR 17592 --- [  restartedMain] j.LocalContainerEntityManagerFactoryBean : Failed to initialize JPA EntityManagerFactory: Could not determine recommended JdbcType for Java type 'com.example.application.data.SamplePerson'
2024-02-05T14:16:01.492-05:00  WARN 17592 --- [  restartedMain] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Could not determine recommended JdbcType for Java type 'com.example.application.data.SamplePerson'
2024-02-05T14:16:01.500-05:00  WARN 17592 --- [  restartedMain] o.s.b.f.support.DisposableBeanAdapter    : Invocation of destroy method failed on bean with name 'inMemoryDatabaseShutdownExecutor': org.h2.jdbc.JdbcSQLNonTransientConnectionException: Database is already closed (to disable automatic closing at VM shutdown, add ";DB_CLOSE_ON_EXIT=FALSE" to the db URL) [90121-224]
2024-02-05T14:16:01.500-05:00  INFO 17592 --- [  restartedMain] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
2024-02-05T14:16:01.503-05:00  INFO 17592 --- [  restartedMain] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.
2024-02-05T14:16:01.508-05:00  INFO 17592 --- [  restartedMain] o.apache.catalina.core.StandardService   : Stopping service [Tomcat]
2024-02-05T14:16:01.519-05:00  WARN 17592 --- [  restartedMain] o.a.c.loader.WebappClassLoaderBase       : The web application [ROOT] appears to have started a thread named [JNA Cleaner] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
 java.base/jdk.internal.misc.Unsafe.park(Native Method)
 java.base/java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:269)
 java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:1759)
 java.base/java.lang.ref.ReferenceQueue.await(ReferenceQueue.java:71)
 java.base/java.lang.ref.ReferenceQueue.remove0(ReferenceQueue.java:143)
 java.base/java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:218)
 com.sun.jna.internal.Cleaner$CleanerThread.run(Cleaner.java:154)
2024-02-05T14:16:01.530-05:00  INFO 17592 --- [  restartedMain] .s.b.a.l.ConditionEvaluationReportLogger :

Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
2024-02-05T14:16:01.553-05:00 ERROR 17592 --- [  restartedMain] o.s.boot.SpringApplication               : Application run failed

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Could not determine recommended JdbcType for Java type 'com.example.application.data.SamplePerson'
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1773) ~[spring-beans-6.1.3.jar:6.1.3]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:599) ~[spring-beans-6.1.3.jar:6.1.3]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:521) ~[spring-beans-6.1.3.jar:6.1.3]
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:325) ~[spring-beans-6.1.3.jar:6.1.3]
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.1.3.jar:6.1.3]
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:323) ~[spring-beans-6.1.3.jar:6.1.3]
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-6.1.3.jar:6.1.3]
        at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1231) ~[spring-context-6.1.3.jar:6.1.3]
        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:949) ~[spring-context-6.1.3.jar:6.1.3]
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:624) ~[spring-context-6.1.3.jar:6.1.3]
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[spring-boot-3.2.2.jar:3.2.2]
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) ~[spring-boot-3.2.2.jar:3.2.2]
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456) ~[spring-boot-3.2.2.jar:3.2.2]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:334) ~[spring-boot-3.2.2.jar:3.2.2]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1354) ~[spring-boot-3.2.2.jar:3.2.2]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1343) ~[spring-boot-3.2.2.jar:3.2.2]
        at com.example.application.Application.main(Application.java:25) ~[classes/:na]
        at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104) ~[na:na]
        at java.base/java.lang.reflect.Method.invoke(Method.java:578) ~[na:na]
        at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:50) ~[spring-boot-devtools-3.2.2.jar:3.2.2]
Caused by: org.hibernate.type.descriptor.java.spi.JdbcTypeRecommendationException: Could not determine recommended JdbcType for Java type 'com.example.application.data.SamplePerson'
        at org.hibernate.type.descriptor.java.spi.UnknownBasicJavaType.getRecommendedJdbcType(UnknownBasicJavaType.java:37) ~[hibernate-core-6.4.1.Final.jar:6.4.1.Final]
        at org.hibernate.boot.model.process.internal.InferredBasicValueResolver.from(InferredBasicValueResolver.java:195) ~[hibernate-core-6.4.1.Final.jar:6.4.1.Final]
        at org.hibernate.mapping.BasicValue.resolution(BasicValue.java:642) ~[hibernate-core-6.4.1.Final.jar:6.4.1.Final]
        at org.hibernate.mapping.BasicValue.buildResolution(BasicValue.java:493) ~[hibernate-core-6.4.1.Final.jar:6.4.1.Final]
        at org.hibernate.mapping.BasicValue.resolve(BasicValue.java:345) ~[hibernate-core-6.4.1.Final.jar:6.4.1.Final]
        at org.hibernate.mapping.BasicValue.resolve(BasicValue.java:335) ~[hibernate-core-6.4.1.Final.jar:6.4.1.Final]
        at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.lambda$processValueResolvers$4(InFlightMetadataCollectorImpl.java:1800) ~[hibernate-core-6.4.1.Final.jar:6.4.1.Final]
        at java.base/java.util.ArrayList.removeIf(ArrayList.java:1682) ~[na:na]
        at java.base/java.util.ArrayList.removeIf(ArrayList.java:1660) ~[na:na]
        at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processValueResolvers(InFlightMetadataCollectorImpl.java:1799) ~[hibernate-core-6.4.1.Final.jar:6.4.1.Final]
        at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses(InFlightMetadataCollectorImpl.java:1785) ~[hibernate-core-6.4.1.Final.jar:6.4.1.Final]
        at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:332) ~[hibernate-core-6.4.1.Final.jar:6.4.1.Final]
        at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:1432) ~[hibernate-core-6.4.1.Final.jar:6.4.1.Final]
        at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1503) ~[hibernate-core-6.4.1.Final.jar:6.4.1.Final]
        at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:75) ~[spring-orm-6.1.3.jar:6.1.3]
        at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:376) ~[spring-orm-6.1.3.jar:6.1.3]
        at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409) ~[spring-orm-6.1.3.jar:6.1.3]
        at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396) ~[spring-orm-6.1.3.jar:6.1.3]
        at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:352) ~[spring-orm-6.1.3.jar:6.1.3]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1820) ~[spring-beans-6.1.3.jar:6.1.3]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1769) ~[spring-beans-6.1.3.jar:6.1.3]
        ... 19 common frames omitted

Solution

  • There are various problems:

    1. The location of the ManyToOne mapping. As the AbstractEntity has the mapping on the fields, the whole class must have the mappings on the fields.

    2. The JoinColumn annotation. The SamplePerson table has no SAMPLE_PERSON_ID. You don't need that configuration at all.

    Here's the correct mapping of Bat and SamplePerson:

    @Entity
    public class Bat extends AbstractEntity {
    
        private String color;
    
        @JsonBackReference
        @ManyToOne
        @JoinColumn(name = "zookeeper")
        private SamplePerson zooKeeper;
    
    
    @Entity
    public class SamplePerson extends AbstractEntity {
    
        @OneToOne(targetEntity = Ape.class)
        @JoinColumn(name="ape")
        private Ape ape;
    
        @JsonManagedReference
        @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "zooKeeper")
        private Set<Bat> bats;
    
    1. The order of the statements in the data.sql and the statements. That's the correct data.sql
    insert into sample_person(version, id, c, d, e) values (1, 1, 'c', 'd', 'e')
    insert into ape(version, id, color) values (1, 1, 'apricot')
    insert into bat(version, id, color, zooKeeper) values (1, 1, 'brown', 1)
    insert into bat(version, id, color, zooKeeper) values (1, 2, 'blue', 1)