简体   繁体   中英

NullPointerException on multi-table primary key JPA when building application

thanks for your time. I've been trying to build my application but no luck so far: What I have:

users:

create table if not exists users (
  id uuid not null,
  created_at timestamp not null,
  updated_at timestamp not null,
  version int8 not null,
  birth_date date not null,
  email varchar(100) not null unique,
  first_name varchar(100) not null,
  gender varchar(30) not null,
  last_name varchar(100) not null,
  password varchar(100) not null,
  picture varchar(100),
  primary key (id)
);

events:

CREATE TABLE events (
  id uuid PRIMARY KEY,
  starts_at timestamp without time zone not null,
  ends_at timestamp without time zone,
  frequency VARCHAR(7) not null default 'none',
  separation integer not null default 1 constraint positive_separation check (separation > 0),
  count integer,
  "until" date,
  timezone_name text not null default 'Etc/UTC',
  is_full_day bool not null default false,
  location_id uuid references locations(id),
  created_at timestamp not null,
  updated_at timestamp not null,
  version int8 not null,
  UNIQUE(id, starts_at),
  CHECK (
      is_full_day = FALSE AND ends_at IS NOT NULL OR
      is_full_day = TRUE)
);

event_attendances:

create table if not exists event_attendances (
    user_id uuid not null,
    event_id uuid not null,
    starts_at timestamp without time zone not null,
    created_at timestamp not null,
    updated_at timestamp not null,
    version int8 not null,
    status varchar(15) not null,
    primary key (user_id, event_id, starts_at),
    FOREIGN KEY (event_id) references events (id),
    FOREIGN KEY (user_id) references users(id)
);

The Java code:

@Table(name = "event_attendances", indexes = { @Index(columnList = 
"status") })
@Entity
public class EventAttendance extends BaseEntityNoId {

@EmbeddedId
private EventAttendanceId id;

@ManyToOne(fetch = FetchType.LAZY, optional = false)
@MapsId("userId")
@JoinColumn(name = "user_id", referencedColumnName = "id")
private User user;

@ManyToOne(fetch = FetchType.LAZY, optional = false)
@MapsId("eventId")
@JoinColumn(name = "event_id", referencedColumnName = "id")
@JoinColumn(name = "starts_at", referencedColumnName = "startsAt")
private Event event;

@Column
@Enumerated(EnumType.STRING)
private EventAttendanceStatus status;

public EventAttendanceId getId() {
    return id;
}

public void setId(EventAttendanceId id) {
    this.id = id;
}

public User getUser() {
    return user;
}

public void setUser(User user) {
    this.user = user;
}

public Event getEvent() {
    return event;
}

public void setEvent(Event event) {
    this.event = event;
}

public EventAttendanceStatus getStatus() {
    return status;
}

public void setStatus(EventAttendanceStatus status) {
    this.status = status;
}

}

EventAttendanceId:

@Embeddable
public class EventAttendanceId implements Serializable {

@Column(name = "user_id")
private UUID userId;

@Column(name = "event_id")
private UUID eventId;

@Column(name = "starts_at")
private LocalDateTime startsAt;

public EventAttendanceId() {
}

public EventAttendanceId(UUID userId, UUID eventId, LocalDateTime startsAt) {
    this.userId = userId;
    this.eventId = eventId;
    this.startsAt = startsAt;
}

public UUID getUserId() {
    return userId;
}

public void setUserId(UUID userId) {
    this.userId = userId;
}

public UUID getEventId() {
    return eventId;
}

public void setEventId(UUID eventId) {
    this.eventId = eventId;
}

public LocalDateTime getStartsAt() {
    return startsAt;
}

public void setStartsAt(LocalDateTime startsAt) {
    this.startsAt = startsAt;
}

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    EventAttendanceId that = (EventAttendanceId) o;
    return userId.equals(that.userId) && eventId.equals(that.eventId) && startsAt.equals(that.startsAt);
}

@Override
public int hashCode() {
    return Objects.hash(userId, eventId, startsAt);
}

}

Finally, my stacktrace:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is java.lang.NullPointerException
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1788)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:609)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:531)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1159)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:913)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:588)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:144)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:767)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:426)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:326)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1311)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1300)
    at com.klustr.main.MainApplication.main(MainApplication.java:10)
Caused by: java.lang.NullPointerException
    at org.hibernate.mapping.PersistentClass.createPrimaryKey(PersistentClass.java:390)
    at org.hibernate.cfg.CreateKeySecondPass.doSecondPass(CreateKeySecondPass.java:31)
    at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses(InFlightMetadataCollectorImpl.java:1693)
    at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses(InFlightMetadataCollectorImpl.java:1657)
    at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:295)
Caused by: java.lang.NullPointerException

    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:1224)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1255)
    at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:58)
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396)
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:341)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1847)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1784)
    ... 17 more

Spring boot version: v2.4.2

I'm not sure if I'm mapping it correctly, but the error is not clear to me. Any help is appreciated!

Looks like this is a Hibernate bug. Please create an issue in the issue tracker( https://hibernate.atlassian.net ) with a test case( https://github.com/hibernate/hibernate-test-case-templates/blob/master/orm/hibernate-orm-5/src/test/java/org/hibernate/bugs/JPAUnitTestCase.java ) that reproduces the issue.

You define the following FK

create table if not exists event_attendances (
    event_id uuid not null,
    -- ...
    FOREIGN KEY (event_id) references events (id),
    -- ...
);

But you use the following mapping:

@Table(name = "event_attendances")
@Entity
public class EventAttendance extends BaseEntityNoId {

   // ...

   @ManyToOne(fetch = FetchType.LAZY, optional = false)
   @MapsId("eventId")
   @JoinColumn(name = "event_id", referencedColumnName = "id")
   @JoinColumn(name = "starts_at", referencedColumnName = "startsAt") // it should be removed !!
   private Event event;

   // ...
}

I guess it should corrected. The @JoinColumn(name = "starts_at", referencedColumnName = "startsAt") annotation should be removed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM