【问题标题】:JPA @MapsId inserting incorrect column nameJPA @MapsId 插入不正确的列名
【发布时间】:2014-09-12 08:19:15
【问题描述】:

尽管遵循了网上的所有示例,但我无法让 @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;

项目.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;

订阅.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, SQL状态:42S22 2014-07-20 11:06:59,193 org.hibernate.engine.jdbc.spi.SqlExceptionHelper - 未知列 '字段列表'中的'subscription_id'

...

... 94 更多原因: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException:未知 “字段列表”中的“订阅 ID”列 sun.reflect.NativeConstructorAccessorImpl.newInstance0(本机方法) 在 sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57) 在 sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) 在 java.lang.reflect.Constructor.newInstance(Constructor.java:526) 在 com.mysql.jdbc.Util.handleNewInstance(Util.java:408) 在 com.mysql.jdbc.Util.getInstance(Util.java:383) 在 com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1062) 在 com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4226) 在 com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4158) 在 com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2615) 在 com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2776) 在 com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2840) 在 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 列: 订阅号

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

我不知道如何解决这个问题。任何建议将不胜感激。

谢谢


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

【问题讨论】:

  • 您使用@MapsId 的目的是什么?你想达到什么目标?
  • 我有一个一对多的关系,其中许多实体都有一个包含一个实体 id 的复合键。
  • 我还在项目的 id 字段和 ProjectId 中使用了 AttributeOverride 和 AttributeOverride。都不能解决问题。

标签: java hibernate jpa


【解决方案1】:

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

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

【讨论】:

  • 谢谢,但我试过了,但它不起作用,因为我收到以下错误:“org.hibernate.MappingException:重复列”,如我原来的帖子中所述。请参阅我的答案以获得最终解决方案。
  • 您有两个问题,列名问题是因为您需要连接列。您的第二个问题应该在一个单独的问题中,因为它与 mapsId 或正在使用的列名无关。
【解决方案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<>();

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

    • 感谢您的建议,但是我已经尝试过了,但没有成功。请参见上文。
    • 我想它可以与@AttributeOverride(name="subscription_id", column=@Column(name="subscriptionId"))一起工作,因为Hibernate在找到@MapsId时默认生成subscription_id名称。但我仍然宁愿使用@JoinColumn,而不是不依赖 Hibernate 的默认名称生成实现。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-28
    • 1970-01-01
    • 2021-07-22
    • 2016-10-07
    • 2014-03-15
    • 2015-04-17
    • 2018-05-27
    相关资源
    最近更新 更多