带有一个外键的组合键 OneToMany Spring Boot JPA Informix

Composite Key with one Foreign Key OneToMany Spring Boot JPA Informix

这是 Informix 数据库的当前结构:

Table: msg_body 
        id (PK)
        kanal
        sender
        ...

Table: msg_user
        id (PK, FK)
        empfaenger (PK)
        datum
        ...

一个msg_user有一个或多个msg_bodies。

msg_body 域 class:

import javax.persistence.*;
import java.io.Serializable;
import java.sql.Timestamp;

@Entity
@Table(name="msg_body")
public class MessageBody implements Serializable {
    @Id
    @Column(name="id")
    private int mb_id;
    @Column(name="kanal")
    private String channel;
    @Column(name="gueltig_von")
    private Timestamp validFrom;
    @Column(name="gueltig_bis")
    private Timestamp validTo;
    @Column(name="sender")
    private String sender;
    @Column(name="erstell_datum")
    private Timestamp createDate;
    @Column(name="prioritaet")
    private int priority;
    @Column(name="nachricht")
    private String message;
    @Column(name="info")
    private String info;
    @Column(name="gueltig")
    private char valid;

    @ManyToOne
    private MessageUser messageUser;

    //getter  + setter
}

msg_user 域 class:

import java.io.Serializable;
import java.sql.Timestamp;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.*;

@Entity
@Table(name="msg_user")
public class MessageUser implements Serializable {
    @EmbeddedId
    UserId mu_id;

    @MapsId("mb_id")
    @JoinColumn(name = "mu_id", referencedColumnName = "id")
    @OneToMany
    private Set<MessageBody> msg_bodies = new HashSet<>();

    @Column(name = "datum")
    private Timestamp receiverDate;
    @Column(name = "versuch")
    private Timestamp tryTime;
    @Column(name = "versuch_anzahl")
    private int tryAmount;
    @Column(name = "status")
    private int state;
    @Column(name = "ip")
    private char ip;

    // getter + setter + hashcode + equals
}

复合键Class:

import java.io.Serializable;
import javax.persistence.*;

@Embeddable
public class UserId implements Serializable
{
    @Column(name="id")
    private int mb_id;
    @Column(name="empfaenger")
    private String receiver;

    // getter + setter + hashcode + equals
}

申请class:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.context.web.SpringBootServletInitializer;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

@Configuration
@ComponentScan("at.company.badge_service")
@EnableAutoConfiguration
@EnableJpaRepositories(basePackages = {"at.company.badge_service.repository"})

public class Application extends SpringBootServletInitializer
{
    public static void main (String[] args)
    {
        SpringApplication.run(Application.class, args);
    }
}

目标是运行这条语句:

public interface BARepository extends JpaRepository<MessageBody, Long>
{
    @Query( "SELECT COUNT(mu.id) FROM MessageUser mu WHERE mu.receiver = :username")
    Long countBA(@Param("username") String username);
}

application.properties 文件:

spring.main.show-banner=false
security.basic.enabled=false
spring.thymeleaf.cache=false

# JACKSON
spring.jackson.mapper.default-view-inclusion=true
#spring.jackson.deserialization.fail-on-unknown-properties=false

security.user.name: username
security.user.password: password

spring.view.prefix: /WEB-INF/views/
spring.view.suffix: .jsp

# DATABASE
spring.jpa.database: INFORMIX
spring.jpa.hibernate.ddl-auto: validate
spring.jpa.properties.hibernate.default_batch_fetch_size: 100
spring.datasource.jndi-name=jdbc/msgdb

ErrorCode NullpointerException:

    2015-04-24 09:30:04,702 [RMI TCP Connection(3)-127.0.0.1] ERROR o.s.boot.SpringApplication - Application startup failed
    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is java.lang.NullPointerException
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1566) ~[spring-beans-4.1.5.RELEASE.jar:4.1.5.RELEASE]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539) ~[spring-beans-4.1.5.RELEASE.jar:4.1.5.RELEASE]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476) ~[spring-beans-4.1.5.RELEASE.jar:4.1.5.RELEASE]
        at org.springframework.beans.factory.support.AbstractBeanFactory.getObject(AbstractBeanFactory.java:303) ~[spring-beans-4.1.5.RELEASE.jar:4.1.5.RELEASE]
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.1.5.RELEASE.jar:4.1.5.RELEASE]
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299) ~[spring-beans-4.1.5.RELEASE.jar:4.1.5.RELEASE]
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194) ~[spring-beans-4.1.5.RELEASE.jar:4.1.5.RELEASE]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110) [na:1.7.0_02]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603) [na:1.7.0_02]
        at java.lang.Thread.run(Thread.java:722) [na:1.7.0_02]
    Caused by: java.lang.NullPointerException: null
    Apr 24, 2015 9:30:04 AM org.apache.catalina.core.ContainerBase addChildInternal
        at org.hibernate.cfg.annotations.CollectionBinder.bindCollectionSecondPass(CollectionBinder.java:1460) ~[hibernate-core-4.3.7.Final.jar:4.3.7.Final]
        at org.hibernate.cfg.annotations.CollectionBinder.bindOneToManySecondPass(CollectionBinder.java:864) ~[hibernate-core-4.3.7.Final.jar:4.3.7.Final]
    Schwerwiegend: ContainerBase.addChild: start: 
        at org.hibernate.cfg.annotations.CollectionBinder.bindStarToManySecondPass(CollectionBinder.java:779) ~[hibernate-core-4.3.7.Final.jar:4.3.7.Final]
    org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/badge_service]]
        at org.hibernate.cfg.annotations.CollectionBinder.secondPass(CollectionBinder.java:728) ~[hibernate-core-4.3.7.Final.jar:4.3.7.Final]at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901)
        at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1426) ~[hibernate-core-4.3.7.Final.jar:4.3.7.Final]

        at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:618)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1625) ~[spring-beans-4.1.5.RELEASE.jar:4.1.5.RELEASE]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1562) ~[spring-beans-4.1.5.RELEASE.jar:4.1.5.RELEASE]
        at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:565)
        ... 58 common frames omitted
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
        at java.lang.Thread.run(Thread.java:722)
    Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is java.lang.NullPointerException
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1566)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
        ... 40 more
    Caused by: java.lang.NullPointerException
        at org.hibernate.cfg.annotations.CollectionBinder.bindCollectionSecondPass(CollectionBinder.java:1460)
        at org.hibernate.cfg.annotations.CollectionBinder.bindOneToManySecondPass(CollectionBinder.java:864)
        at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60)
        at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:343)
        at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:318)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1625)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1562)
        ... 58 more

    Apr 24, 2015 9:30:04 AM org.apache.tomcat.util.modeler.BaseModelMBean invoke
    Schwerwiegend: Exception invoking method manageApp
    java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/badge_service]]
        at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:904)
        at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877)
        at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:649)
        at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:618)
        at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:565)
        at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:553)
        at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:808)
        at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:667)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
        at java.lang.Thread.run(Thread.java:722)

    Apr 24, 2015 9:30:04 AM org.apache.tomcat.util.modeler.BaseModelMBean invoke
    Schwerwiegend: Exception invoking method createStandardContext
    javax.management.RuntimeOperationsException: Exception invoking method manageApp
        at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:309)
        at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
        at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:791)
        at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:618)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
        at java.lang.Thread.run(Thread.java:722)
    Caused by: java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/badge_service]]
        at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:904)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:601)
        at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:301)
        ... 31 more

我试图在网上找到解决方案,但 none 对我的情况有效。尤其是组合键中的外键似乎是一个很少见的问题。 我很清楚,向 msg_user-table 添加代理键会容易得多,但我必须解决这个问题,所以如果有人能告诉我我会很高兴如何以正确的方式使用关系对域 classes 进行编码。 如果您需要更多信息,请随时向他们索取! 非常感谢!

过了一段时间我找到了解决办法:

MessageBody 域类:

import javax.persistence.*;
import java.io.Serializable;
import java.sql.Timestamp;
import java.util.HashSet;
import java.util.Set;

@Entity
@Table(name="msg_body")
public class MessageBody implements Serializable
{
    @Id
    @Column(name="id")
    private int msgb_id;

    @Column(name="kanal", columnDefinition = "char")
    private String channel;

    @Column(name="gueltig_von")
    private Timestamp validFrom;

    @Column(name="gueltig_bis")
    private Timestamp validTo;

    @Column(name="sender")
    private String sender;

    @Column(name="erstell_datum")
    private Timestamp createDate;

    @Column(name="prioritaet")
    private int priority;

    @Column(name="nachricht")
    private String message;

    @Column(name="info", columnDefinition = "lvarchar")
    private String info;

    @Column(name="gueltig")
    private char valid;

    @OneToMany
    @JoinColumn(name = "id")
    private Set<MessageUser> message_users = new HashSet<>();

    // getter  + setter
}

CompositeKey 域类:

import java.io.Serializable;
import javax.persistence.*;

@Embeddable
public class MessageUserPK implements Serializable
{
    private int mb_id;
    private String receiver;

    // getter + setter + hashcode + equals
}

消息用户域类:

import java.io.Serializable;
import java.sql.Timestamp;
import javax.persistence.*;

@Entity
@Table(name="msg_user")
public class MessageUser implements Serializable
{
    @EmbeddedId
    @AttributeOverrides
    ({
            @AttributeOverride(name = "mb_id", column = @Column(name = "id")),
            @AttributeOverride(name = "receiver", column = @Column(name = "empfaenger"))
    })
    MessageUserPK mu_id;

    @Column(name = "datum")
    private Timestamp receiverDate;

    @Column(name = "versuch")
    private Timestamp tryTime;

    @Column(name = "versuch_anzahl")
    private int tryAmount;

    @Column(name = "status")
    private int state;

    @Column(name = "ip")
    private char ip;

    @ManyToOne
    @MapsId("mb_id")
    @JoinColumn(name = "id")
    private MessageBody messageBody;

    // getter + setter + hashcode + equals
}

问题中的关系是双向的,但我将 Collection 放在 MessageBody-Domain 类中。在 "AttributOverrides" 等其他一些修复之后,它起作用了。希望我能帮助另一个人解决问题![​​=13=]