【问题标题】:Why am I obtaining this "Repeated column in mapping for entity" into an Hibernate entity? What is the best way to handle this situation?为什么我要将此“实体映射中的重复列”获取到 Hibernate 实体中?处理这种情况的最佳方法是什么?
【发布时间】:2016-12-11 21:54:27
【问题描述】:

我不太喜欢 Hibernate,我有以下问题\怀疑。

我有这种情况:

1) 我有这个 Room 实体类,它代表一个住宿的房间:

@Entity
@Table(name = "room")
public class Room implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;


    @ManyToOne
    @JoinColumn(name = "id_accomodation_fk", nullable = false)
    private Accomodation accomodation;

    @ManyToOne
    @JoinColumn(name = "id_room_tipology_fk", nullable = false)
    private RoomTipology roomTipology;

    @OneToMany(mappedBy = "room")
    private List<RoomMedia> roomMediaList;

    @Column(name = "room_number")
    private String number;

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

    @Column(name = "room_description")
    private String description;

    @Column(name = "is_enabled")
    private Boolean isEnabled;

    ........................................................................
    ........................................................................
    GETTER AND SETTER METHODS
    ........................................................................
    ........................................................................
}

2) 然后我有这个 RoomMedia 实体类,它代表与特定 Room 实体相关的照片:

@Entity
@Table(name = "room_media")
public class RoomMedia {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    @Column(name = "id_room")
    private Long idRoom;

    @ManyToOne
    @JoinColumn(name = "id_room", nullable = false)     // da rinominare anche sul DB in room_fk
    private Room room;

    @Lob
    @Column(name = "media")
    private byte[] media;

    private String description;

    ........................................................................
    ........................................................................
    GETTER AND SETTER METHODS
    ........................................................................
    ........................................................................

}

正如您在前面的代码中看到的,这两个实体类以这种方式链接在一起:

Room 实例代表一个特定的房间并包含其照片列表,以这种方式:

@OneToMany(mappedBy = "room")
private List<RoomMedia> roomMediaList;

这意味着一个房间链接到许多 RoomMedia 实例。 mappedBy = "room" 表示要在 RoomRoomMedia 之间建立链接,请使用 RoomMediaroom 字段> 实体(表示 RoomMedia 实例的特定房间)。

然后在 RoomMedia 实体类中我有这个链接:

@ManyToOne
@JoinColumn(name = "id_room", nullable = false)    
private Room room;

Where 表示许多 RoomMedia 实例与单个 Room 实例相关。 Join 操作是使用 room_media 表上的 id_room 字段完成的(它是在表级别而不是实体级别完成的)。

如果所有这些推理有问题,请纠正。

我的问题是,在应用程序启动时,我收到此错误消息:

Caused by: javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.persistenceException(EntityManagerFactoryBuilderImpl.java:1249)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.access$600(EntityManagerFactoryBuilderImpl.java:120)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:860)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:850)
    at org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.withTccl(ClassLoaderServiceImpl.java:425)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:849)
    at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60)
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:353)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:373)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:362)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1642)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1579)
    ... 39 more
Caused by: org.hibernate.MappingException: Repeated column in mapping for entity: com.betrivius.domain.RoomMedia column: id_room (should be mapped with insert="false" update="false")
    at org.hibernate.mapping.PersistentClass.checkColumnDuplication(PersistentClass.java:709)
    at org.hibernate.mapping.PersistentClass.checkPropertyColumnDuplication(PersistentClass.java:731)
    at org.hibernate.mapping.PersistentClass.checkColumnDuplication(PersistentClass.java:753)
    at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:506)
    at org.hibernate.mapping.RootClass.validate(RootClass.java:270)
    at org.hibernate.cfg.Configuration.validate(Configuration.java:1360)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1851)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:857)
    ... 48 more

为什么 Hibernate 不能同时处理这两者?问题是什么?我该如何解决?

我认为这可能取决于在 RoomMedia 实例中我仍然有不再需要的 id_room 字段,因为在这个实体中我也有把:

@ManyToOne
@JoinColumn(name = "id_room", nullable = false)    
private Room room;

它本身就包含这个 id。

所以我认为删除这个字段:

@Column(name = "id_room")
private Long idRoom;

我会解决我的问题,是吗?

但现在我可能会遇到另一个问题:在我的 DAO 中,我可能会遇到一些涉及 idRoom 的复杂查询。因此,为方便起见,我会将这些 private Room room;private Long idRoom; 字段放入我的 RoomMedia 实体类中。

我怎样才能同时避免这个问题?

【问题讨论】:

  • 我会删除多余的“idRoom”。在 JPQL 查询中,您仍然可以使用“WHERE n.room.id = :roomId”之类的内容。
  • 在你的“房间”对象中,你有一个“idRoom”属性(或者可能是一个“id”属性)。然后,您可以从 RoomMedia 开始编写 HQL 查询: from RoomMedia r where r.Room.idRoom = 1。

标签: hibernate jpa hibernate-mapping


【解决方案1】:

您绝对应该从映射中删除此列

@Column(name = "id_room")
private Long idRoom;

Hibernate 也会这样告诉你。

但现在我可能会遇到另一个问题:在我的 DAO 中,我可能会遇到一些涉及 idRoom 的复杂查询。所以,为了方便起见,我会同时拥有这两个私人房间;和私人长idRoom;字段到我的 RoomMedia 实体类中。

正确的映射是

@ManyToOne
@JoinColumn(name = "id_room", nullable = false)    
private Room room;

并且它为您提供所需的一切

查询示例

Query query1 = em.createQuery("select rm from RoomMedia rm where rm.room.id = :id");

Query query2 = em.createQuery("select rm from RoomMedia rm join rm.room r where r.id = :id");

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-05-12
    • 1970-01-01
    • 2017-06-26
    • 2013-10-31
    • 2014-11-24
    • 2022-10-15
    • 2012-05-04
    相关资源
    最近更新 更多