JPA @MapsId插入错误的列名

时间:2014-07-21 18:01:38

标签: java hibernate jpa

尽管在网上播放了所有示例,但我无法让@MapsId工作。

这是我的设置:

的pom.xml:

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-entitymanager</artifactId>
    <version>4.3.5.Final</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.31</version>
</dependency>

DDL脚本:

CREATE TABLE Subscription (
    id bigint not null primary key auto_increment,
    active boolean not null,
    maxNumUsers int not null
)ENGINE=InnoDB;

CREATE TABLE t.Project (
    name varchar(32) not null,
    subscriptionId bigint not null
)ENGINE=InnoDB;

ALTER TABLE t.Project ADD CONSTRAINT `projectPK` PRIMARY KEY (name, subscriptionId);
ALTER TABLE t.Project ADD CONSTRAINT `projectSubscriptionFK` FOREIGN KEY (subscriptionId) REFERENCES t.Subscription(id);

ProjectId.java:

@Embeddable
public class ProjectId implements Serializable {
    private Long subscriptionId;
    private String name;

Project.java:

@Entity
@Table(schema = "t")
public class Project {
    @EmbeddedId
    private ProjectId id;

    @ManyToOne
    @MapsId("subscriptionId")
    //@JoinColumn(name = "subscriptionId", referencedColumnName = "id", insertable = false, updatable = false)
    private Subscription subscription;

Subscription.java:

@Entity
@Table(schema = "t")
public class Subscription {

    @OneToMany(mappedBy = "subscription", cascade = CascadeType.ALL)
    private Map<ProjectId, Project> projects = new HashMap<>();

当我执行插入时,会发生以下错误:

  

Hibernate:插入到t.Project(name,subscription_id)值(?,?)   2014-07-20 11:06:59,193   org.hibernate.engine.jdbc.spi.SqlExceptionHelper - SQL错误:1054,   SQLState:42S22 2014-07-20 11:06:59,193   org.hibernate.engine.jdbc.spi.SqlExceptionHelper - 未知列   '字段列表'中的'subscription_id'

     

...

     

... 94更多引起:   com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException:未知   列''subscription_id'在'字段列表'中   sun.reflect.NativeConstructorAccessorImpl.newInstance0(本机方法)     在   sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)     在   sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)     at java.lang.reflect.Constructor.newInstance(Constructor.java:526)     在com.mysql.jdbc.Util.handleNewInstance(Util.java:408)at   com.mysql.jdbc.Util.getInstance(Util.java:383)at   com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1062)at at   com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4226)at at   com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4158)at at   com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2615)at at   com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2776)at at   com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2840)at   com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2082)     在   com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2334)     在   com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2262)     在   com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2246)     在   org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:187)     ... 114更多

如果我取消注释 Project.subscription 上的@JoinColumn并重新部署,我会收到此错误:

  

... 21更多引起:org.hibernate.MappingException:重复列   在集合的映射中:t.Subscription.projects列:   subscriptionId

我也尝试删除@MapsId,我仍然遇到重复的列错误。

我很难过如何解决这个问题。任何建议将不胜感激。

由于


更新:如果我使Subscription.projects成为列表而不是地图,我将JoinColumn添加到project.subscription它可以工作。但是,如果我将subscription.projects更改回地图,我会再次开始获取org.hibernate.MappingException:Repeated列。显然我真的想使用地图,所以我会继续挖掘。

3 个答案:

答案 0 :(得分:4)

使用mapsId注释时,您指定关系共享并控制由Id映射映射的字段,因此关系映射中的字段将覆盖Id映射中的字段。这意味着JPA将使用subscription_id默认值,除非您指定了注释掉的连接列:

@JoinColumn(name = "subscriptionId", referencedColumnName = "id")

答案 1 :(得分:2)

好的,问题是我需要将@MapKey添加到subscription.projects,否则当我添加@JoinColumn

时它会抱怨“org.hibernate.MappingException:Repeated column”

感谢您的建议

以下是最终代码:

@Embeddable
public class ProjectId implements Serializable {
    private Long subscriptionId;
    private String name;

@Entity
@Table(schema = "t")
public class Project {
    @EmbeddedId
    private ProjectId id;

    @ManyToOne
    @MapsId("subscriptionId")
    @JoinColumn(name = "subscriptionId", referencedColumnName = "id", insertable = false, updatable = false)
    private Subscription subscription;


@Entity
@Table(schema = "t")
public class Subscription {

    @OneToMany(mappedBy = "subscription", cascade = CascadeType.ALL)
    @MapKey(name = "id")
    private Map<ProjectId, Project> projects = new HashMap<>();

答案 2 :(得分:1)

我认为您需要@AttributeOverride来覆盖默认的连接列名称:

@EmbeddedId
@AttributeOverride(name="subscriptionId", column=@Column(name="subscriptionId"))
private ProjectId id;