简体   繁体   English

Java Hibernate JPA 创建一个实体并加入同一列引用的两个不同的表,具有相同的列名

[英]Java Hibernate JPA create an entity and Join two different tables referenced by the same column, with same column name

I have an issue that want to resolve using just annotations, and not two different query to obtain the data.我有一个问题只想使用注释来解决,而不是使用两个不同的查询来获取数据。 I need to join two different tables with the same column id.我需要连接两个具有相同列 ID 的不同表。 I have Travels, and at certain time, the rows in Travel are erased, but now TravelHistory (a table to save data) have the row with just the data needed to save (and with the same id of Travel... make sense).我有 Travels,并且在特定时间,Travel 中的行被删除,但现在 TravelHistory(用于保存数据的表)的行只包含需要保存的数据(并且具有相同的 Travel id ...有意义) . At certain time, Travel and TravelHistory may coexist.在某些时候,Travel 和 TravelHistory 可能会共存。

I want to have the two different classes mapped by same id ( travel_id is the name of column), something like this (code is simplified):我想让两个不同的类由相同的 id 映射( travel_id是列的名称),就像这样(代码被简化):

@Entity
@Table(name = "travel_audit")
public class TravelAudit {
    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "travel_id")
    private Travel travel;
    
    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "travel_id")
    private TravelHistory travelHistory;

}

but Hibernate seems to not like that (having the same name = "travel_id" ), so I have errors to create the Bean.但 Hibernate 似乎不喜欢那样(具有相同的name = "travel_id" ),所以我在创建 Bean 时出错。

For this answer I put a little more effort, and all detail, so to have more references to the tables:对于这个答案,我付出了更多的努力和所有的细节,以便对表格有更多的参考:

@Column(name = "travel_id")
private Long travelId;

@OneToOne(targetEntity = Travel.class, fetch = FetchType.LAZY)
@JoinColumn(name = "travel_id", table = "travel")
private Travel travel;

@OneToOne(targetEntity = TravelHistory.class, fetch = FetchType.LAZY)
@JoinColumn(name = "travel_id", table = "travel_history")
private TravelHistory travelHistory;

But it didn't work.但它没有用。

After that I want to make an Optional<TravelAudit> findByTravelId(Long travelId);之后我想做一个Optional<TravelAudit> findByTravelId(Long travelId); and obtain Travel and/or TravelHistory并获取 Travel 和/或 TravelHistory

How can I do this?我怎样才能做到这一点? Unfortunately I think I'm going to have to retrieve the travel_id (it's a Long) and get the other tables separately.不幸的是,我认为我将不得不检索 travel_id(它很长)并分别获取其他表。

The error is:错误是:

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; org.springframework.beans.factory.BeanCreationException:在类路径资源 [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class] 中定义名称为“entityManagerFactory”的 bean 创建时出错:调用 init 方法失败; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory嵌套异常是 javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory

The mapping for your audit Entity might be:您的审计实体的映射可能是:

@Entity
@Table(name = "travel_audit")
public class TravelAudit {
    @Id
    @Column(name="travel_id")
    private String travelId;

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "travel_id", insertable=false, updatable=false)
    private Travel travel;
    
    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "travel_id", insertable=false, updatable=false)
    private TravelHistory travelHistory;
}

If you are using JPA/Hibernate to generate the DDL, you'll want to make sure there isn't a constraint generated for the travel_audit.travel_id -> travel table reference, as it will get broken any time your app tries to delete travel rows still referenced by a travel audit instance.如果您使用 JPA/Hibernate 生成 DDL,您需要确保没有为 travel_audit.travel_id -> travel 表引用生成约束,因为每当您的应用程序尝试删除旅行时它都会被破坏旅行审计实例仍然引用的行。

Having a basic mapping (travelId) will allow you to query using the value without having to join between the two tables and complicate your queries as the default inner join would break the logic you need.拥有一个基本映射 (travelId) 将允许您使用该值进行查询,而不必在两个表之间进行联接,并且会使您的查询复杂化,因为默认的内部联接会破坏您需要的逻辑。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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