jpa试图强迫我拥有一个名为“id”的属性和数据库列

ybzsozfc  于 2021-06-20  发布在  Mysql
关注(0)|答案(2)|浏览(247)

我有一个mysql innodb数据库表,其中有两列名为follower\u user\u id和follower\u user\u id,这两列都构成了主键。
我试图在springboot中Map它们,但错误消息不断告诉我需要一个名为'id'的属性。但此表没有“id”列。
而且,jpa甚至在表中自动创建一个名为'id'的列,这绝对不是我想要的。
基本上,当一行被插入到这个表中时,将提供follower\u user\u id和follower\u user\u id,并且组合形成主键。没有自动生成的id。
如何告诉jpa我不需要名为'id'的属性,前面提到的列构成主键,并且没有自动生成的键?谢谢!

import java.io.Serializable;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.IdClass;

import org.springframework.data.jpa.domain.AbstractPersistable;

@Entity
@IdClass(FollowerId.class)
public class Follower extends AbstractPersistable<Long> implements Serializable {
    private static final long serialVersionUID = 23456789L;

    @Id
    private Long followerUserId;

    @Id
    private Long followedUserId;

    public Long getFollowerUserId() {
        return followerUserId;
    }

    public void setFollowerUserId(Long followerUserId) {
        this.followerUserId = followerUserId;
    }

    public Long getFollowedUserId() {
        return followerUserId;
    }

    public void setFollowedUserId(Long followedUserId) {
        this.followedUserId = followedUserId;
    }
}

import java.io.Serializable;

public class FollowerId implements Serializable {
    private Long followerUserId;
    private Long followedUserId;

    public FollowerId() {
    }

    public FollowerId(Long followerUserId, Long followedUserId) {
        this.followerUserId = followerUserId;
        this.followedUserId = followedUserId;
    }

    public Long getFollowerUserId() {
        return followerUserId;
    }

    public void setFollowerUserId(Long followerUserId) {
        this.followerUserId = followerUserId;
    }

    public Long getFollowedUserId() {
        return followerUserId;
    }

    public void setFollowedUserId(Long followedUserId) {
        this.followedUserId = followedUserId;
    }

    public int hashCode() {
        return (int) (getFollowerUserId() + getFollowedUserId());
    }

    public boolean equals(Object obj) {
        if (obj == this) return true;
        if (!(obj instanceof FollowerId)) return false;
        if (obj == null) return false;
        FollowerId pk = (FollowerId) obj;
        return pk.getFollowerUserId() == getFollowerUserId() && 
            pk.getFollowedUserId() == getFollowedUserId();
    }
}

我得到的错误是:

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 org.hibernate.PropertyNotFoundException: Unable to locate property named id on com.mightyjava.model.FollowerId
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1628) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1081) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:856) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122) ~[spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:737) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:370) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:314) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1162) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1151) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
    at com.mightyjava.Application.main(Application.java:12) [classes/:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_161]
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_161]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_161]
    at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_161]
    at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) [spring-boot-devtools-1.5.2.RELEASE.jar:1.5.2.RELEASE]
Caused by: org.hibernate.PropertyNotFoundException: Unable to locate property named id on com.mightyjava.model.FollowerId
    at org.hibernate.type.ComponentType.getPropertyIndex(ComponentType.java:740) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.jpa.internal.metamodel.AttributeFactory$3.resolveMember(AttributeFactory.java:973) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.jpa.internal.metamodel.AttributeFactory$5.resolveMember(AttributeFactory.java:1024) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.jpa.internal.metamodel.AttributeFactory.determineAttributeMetadata(AttributeFactory.java:449) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.jpa.internal.metamodel.AttributeFactory.buildIdAttribute(AttributeFactory.java:128) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.jpa.internal.metamodel.MetadataContext.applyIdMetadata(MetadataContext.java:303) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.jpa.internal.metamodel.MetadataContext.wrapUp(MetadataContext.java:231) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.jpa.internal.metamodel.MetamodelImpl.buildMetamodel(MetamodelImpl.java:82) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.jpa.internal.EntityManagerFactoryImpl.<init>(EntityManagerFactoryImpl.java:113) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:890) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
    at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) ~[spring-orm-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:353) ~[spring-orm-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:370) ~[spring-orm-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:359) ~[spring-orm-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1687) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1624) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    ... 21 common frames omitted
w8biq8rn

w8biq8rn1#

呃,看来问题出在扩展abstractpersistable上了。这个超类强迫我拥有一个id属性。我已经把这个去掉了,现在一切都好了。
我借用了一些我在网上找到的代码,这就是为什么我要扩展它,但看起来我不需要它。

7lrncoxx

7lrncoxx2#

您需要一个复合主键。
创建一个类,该类表示要组成键的两个值。这是一个可嵌入的id。

@Embeddable
public class FollowId implements Serializable {

    @Column(name = "followerUserId", nullable = false)
    private Long followerUserId;

    @Column(name = "followedUserId", nullable = false)
    private Long followedUserId;

}

接下来,您可以将这个类用作实体中的id。

@Entity
public class Follower implements Serializable {

    @EmbeddedId
    private FollowId followId;

    //other stuff
}

您可以像访问常规对象一样访问id的特定部分,例如:

Follower f = new Follower();
f.getFollowId().getFollowerUserId();
f.getFollowId().getFollowedUserId();

在jpql中,您也可以这样访问它们:

select f from Follower as f where followId.followerUserId = 1 AND followId.followedUserId = 1;

编辑:
idclass类
这似乎是另一种我不熟悉的合成键的方法。看起来需要一个表示id的类,并且在实体中必须有Map到复合主键中的值的字段。然后用@idclass()注解实体,其中包含表示复合键的类。像这样:

@Entity
@IdClass(FollowId.class)
public class Follower implements Serializable {

    @Id
    private Long followerUserId;

    @Id
    private Long followedUserId;

    //other stuff
}

public class FollowId implements Serializable {
    private Long followerUserId;
    private Long followedUserId;

    //other stuff

}

由于我没有真正使用@idclass方法,因此我鼓励您进一步阅读:
idclass示例
objectdb页

相关问题