【问题标题】:Hibernate (on postgres) dropping Schema from @JoinTableHibernate(在 postgres 上)从 @JoinTable 中删除 Schema
【发布时间】:2015-07-21 00:29:37
【问题描述】:

我正在使用在 Postgres 4 数据库上运行的 Hibernate 4.3.10.Final(带有 SpringData JPA)并且遇到了一个非常奇怪的错误。我们的应用程序使用默认“公共”模式之外的数据库,当我们尝试插入数据时,Hibernate 会丢弃正确的模式。

我们的模型由一个抽象的“日志”类组成,该类使用单类继承来允许许多不同的对象类型插入相关的日志消息。请参阅下面的代码。

架构已经存在(hibernate 不会创建它)并且启动验证运行良好,但是当尝试插入新记录时,我们收到错误 relation "booking_log" 不存在 -- 这缺少架构修饰符(例如 customapp 出于我们的目的)。请参阅下面日志中的第一行,以了解其他插入语句的外观。

我已经挖掘了映射阶段并验证了 Hibernate 确实从 @JoinTable 注释中获取了架构,但不确定我们是如何丢失它的。

任何帮助调试或可能的解决方案将不胜感激。

谢谢!


Log - 抽象超类

@MappedSuperclass
@Table(name="log", schema=Constants.DB_SCHEMA)
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="log_type_id", discriminatorType = DiscriminatorType.INTEGER)
public abstract class Log {

    @Id
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="log_seq_gen")
    @SequenceGenerator(allocationSize = 1, name="log_seq_gen", sequenceName=Constants.DB_SCHEMA + ".log_id_seq")
    private Long id;

    // ...     

}

预订日志

@Entity
@DiscriminatorValue("2")
public class BookingLog extends Log implements TenantResource<Company,Long> {

    @JoinTable(name="booking_log",
        schema = Constants.DB_SCHEMA,
        joinColumns = { @JoinColumn(name="log_id", referencedColumnName="id", nullable=false, updatable=false)},
        inverseJoinColumns = { @JoinColumn(name="booking_id", referencedColumnName="id", nullable=false, updatable=false)})
    @ManyToOne(cascade=CascadeType.ALL)
    private Booking booking;

    ///... 

    }

** 日志 **

2015-07-20_18:14:09.055 DEBUG org.hibernate.SQL - insert into customapp.booking_product (created_dt, created_by, modified_dt, modified_by, include_in_payroll, include_in_revenue, booking_id, description, payroll_percent, price, product_id, qty, id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
2015-07-20_18:14:09.072 DEBUG org.hibernate.SQL - insert into booking_log (log_date, details, log_time, user_id, booking_id, id) values (?, ?, ?, ?, ?, ?)
2015-07-20_18:14:09.176 DEBUG o.h.e.jdbc.spi.SqlExceptionHelper - could not execute statement [n/a]
org.postgresql.util.PSQLException: ERROR: relation "booking_log" does not exist

【问题讨论】:

  • 根据您的@JoinTable 配置,booking_log 表的插入语句应该类似于“插入到 booking_log (log_id, booking_id) 值 (?, ?)”。我认为这是第一个需要解决的问题。很奇怪,Hibernate 不建议使用两次相同的表名(在您的关联中,也可能在其他实体中)所以...也许您是在引用另一个实体类/包?
  • @Guillermo 实际上还有一些字段我为了简洁而省略了,所以插入的参数是正确的。这种关系是单向的,所以在这种情况下,Booking 没有对日志的引用。会不会是这个问题?
  • 写评论太大了,看我的回复帖。

标签: java spring hibernate postgresql jpa


【解决方案1】:

根据您的 @JoinTable 配置和 hibernate 生成的插入语句,问题在于您尝试向 booking_log 表添加额外字段/数据的方式。

我需要有关您的模型的更多详细信息才能确定,但​​我认为您使用的是连接表和其他东西,而不是创建一个模拟连接表的类。

我的意思是,你有这个

BookingLog (*) --------------------------------------> (1) Booking

但我认为你真的需要这个

BookingLog (1) ---> (1) BookingLogAssociation (*) ---> (1) Booking

那么映射会是这样的,

@Entity
@DiscriminatorValue("2")
public class BookingLog extends Log implements TenantResource<Company,Long> {

  @OneToOne(mappedBy="bookingLog")
  private BookingLogAssociation booking;

}

注意BookingLogAssociation的属性,它们是您要在booking_log表中添加的额外字段/数据。

@Entity
@Table(name="booking_log")
@IdClass(BookingLogAssociationId.class)
public class BookingLogAssociation {

  @Id
  private long log_id;
  @Id
  private long booking_id;

  @OneToOne
  @PrimaryKeyJoinColumn(name="log_id", referencedColumnName="id")
  private BookingLog bookingLog;

  @ManyToOne
  @PrimaryKeyJoinColumn(name="booking_id", referencedColumnName="id")
  private Booking booking;

  @Column(name="log_date")
  @Temporal(TemporalType.DATE)
  private Calendar logDate;

  @Column(name="log_time")
  @Temporal(TemporalType.TIME)
  private Calendar logTime;

  @ManyToOne
  @JoinColumn(name="user_id")
  private User user;
  // Could be just an attribute too
  //@Column(name="user_id")
  //private long userId;
  ...
}

BookingLogAssociationId 类,表示 BookingLogAssociation 的复合键。

public class BookingLogAssociationId implements Serializable {

  private long log_id;

  private long booking_id;

  public int hashCode() {
    return (int)(log_id + booking_id);
  }

  public boolean equals(Object object) {
    if (object instanceof BookingLogAssociationId) {
      BookingLogAssociationId otherId = (BookingLogAssociationId) object;
      return (otherId.log_id == this.log_id) && (otherId.booking_id == this.booking_id);
    }
    return false;
  }

您可以阅读有关此选项的更多信息here

【讨论】:

    猜你喜欢
    • 2023-03-13
    • 1970-01-01
    • 2014-08-22
    • 1970-01-01
    • 1970-01-01
    • 2016-04-22
    • 1970-01-01
    • 2020-12-20
    • 2021-05-09
    相关资源
    最近更新 更多