【问题标题】:Hibernate generates extra tableHibernate 生成额外的表
【发布时间】:2019-08-01 09:50:34
【问题描述】:

我有一个这样的实体

@Entity
@Table(name = "past_price")
public class PastPrice {

    @Id
    private String symbol;
    @OneToMany(fetch = FetchType.EAGER,cascade = CascadeType.ALL)
    private Set<Price> prices = null;

    public String getSymbol() {
        return symbol;
    }

    public void setSymbol(String symbol) {
        this.symbol = symbol;
    }

    public Set<Price> getPrices() {
        return prices;
    }

    public void setPrices(Set<Price> prices) {
        this.prices = prices;
    }

}

Price实体是这样的

@Entity
public class Price {
    @Id
    @Temporal(TemporalType.TIMESTAMP)
    private Date date;
    private String price;

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    public String getPrice() {
        return price;
    }

    public void setPrice(String price) {
        this.price = price;
    }

}

我想要做的是,创建一个名为past_price 的表,它与Price 实体有OneToMany 关系。我有休眠属性spring.jpa.hibernate.ddl-auto=update,所以每当我运行它时,都会创建3个表1. past_price2. past_price_prices3. price。但我只是想创建 2 个表 past_priceprice。任何帮助,将不胜感激。谢谢

【问题讨论】:

  • 我了解 hibernate 属性的 create 或 create-drop 值,但每次即使使用不同的值,表格也会以相同的方式生成。
  • in @OneToMany(fetch = FetchType.EAGER,cascade = CascadeType.ALL) private Set&lt;Price&gt; prices = null; add targetEntity = Price.class 这个只会创建两个表 price 和 past_price。

标签: java hibernate spring-boot spring-mvc spring-data-jpa


【解决方案1】:

事实上,问题在于您没有为实体提供其他映射。 hibernate 如何识别与PastPrice 相关的Price? Hibernate 不能(但我不确定)在 Price 中存储相关 id 的数组。

默认情况下,如果您只需要 2 个表,则需要在 Price 中添加字段:

@ManyToOne(...)
private PastPrice pastPrice;

在这种情况下,在表 Price hibernate 中生成 id 为“父”价格的 colymn。因此,对于当前的映射,2 个表就足够了。

它会像这样工作:

select * from Price p join PastPrice pp on pp.id = p.past_price

【讨论】:

    【解决方案2】:

    javaDoc

    拥有关系的字段。除非关系是单向的,否则是必需的。

    使用 targetEntity=price.class

     class pastPrice{
             @OneToMany(targetEntity=Price.class,fetch = FetchType.EAGER,cascade = CascadeType.ALL)
             private Set<Price> prices = null;
        }
    

    或使用 mappedby=price

    class pastPrice{
         @OneToMany(mappedby="Price",fetch = FetchType.EAGER,cascade = CascadeType.ALL)
          private Set<Price> prices = null;
    }
    
       @Entity("Price)
        class Price{
    }
    

    【讨论】:

      【解决方案3】:

      您应该添加“mappedBy”来声明哪个字段是关联表。

      还在 Price 实体中添加 ManyToOne。

      价格实体:

      @ManyToOne(fetch = FetchType.EAGER)
      @JoinColumn("past_price_fk")
      private PastPrice pastPrice;
      

      PastPrice 实体:

      @OneToMany(fetch = FetchType.EAGER,cascade = CascadeType.ALL, mappedBy = "pastPrice")
      private Set<Price> prices = null;
      

      【讨论】:

        【解决方案4】:

        使用@JoinColumn 告诉hibernate 在价格表中创建一个列并使用它来连接。将您的代码更改为以下内容:

        @OneToMany(fetch = FetchType.EAGER,cascade = CascadeType.ALL)
        @JoinColumn(name = "fk_past_price")
        private Set<Price> prices = null;
        

        这将在价格表中创建一个名为 fk_past_price 的列,并且不会创建第三个表。

        P.S.:如果没有充分的理由使用单向关联,请改用双向关联。如下:

        @Entity
        @Table(name = "past_price")
        public class PastPrice {
        
            @Id
            private String symbol;
            @OneToMany(mappedBy = "pastPrice", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
            private Set<Price> prices = null;
        
            public String getSymbol() {
                return symbol;
            }
        
            public void setSymbol(String symbol) {
                this.symbol = symbol;
            }
        
            public Set<Price> getPrices() {
                return prices;
            }
        
            public void setPrices(Set<Price> prices) {
                this.prices = prices;
            }
        
        }
        

        价格:

        @Entity
        public class Price {
            @Id
            @Temporal(TemporalType.TIMESTAMP)
            private Date date;
            private String price;
        
            @ManyToOne
            @JoinColumn(name = "past_price_symbol", nullable = false)
            private PastPrice pastPrice;
        
            public PastPrice getPastPrice() {
              return pastPrice;
            }
        
            public void setPastPrice(PastPrice pastPrice) {
              this.pastPrice = pastPrice;
            }
        
            public Date getDate() {
                return date;
            }
        
            public void setDate(Date date) {
                this.date = date;
            }
        
            public String getPrice() {
                return price;
            }
        
            public void setPrice(String price) {
                this.price = price;
            }
        
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多