theanilpaudel
theanilpaudel

Reputation: 3478

Hibernate generates extra table

I have an Entity like this

@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;
    }

}

And the Price entity is like this

@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;
    }

}

What I am trying to do is, create a table with name past_price and it has OneToMany relationship with Price entity. I have hibernate property spring.jpa.hibernate.ddl-auto=update so whenever I run this there are 3 tables created 1. past_price 2. past_price_prices and 3. price. But I am only trying to create 2 tables past_price and price. Any help would be appreciated. Thanks

Upvotes: 2

Views: 1223

Answers (4)

Aditya Narayan Dixit
Aditya Narayan Dixit

Reputation: 2119

Use @JoinColumn to tell hibernate to create a column in price table and use that for joining. Change your code to below:

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

This will create a column named fk_past_price in price table and no third table will be created.

P.S.: Use bidirectional association instead if there's no strong reason to go with uni-directional. Like below:

@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;
    }

}

Price:

@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;
    }

}

Upvotes: 1

hamid rostami
hamid rostami

Reputation: 136

You should add "mappedBy" to declare which field is relate tables.

also add ManyToOne in Price entity.

Price Entity :

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

PastPrice Entity :

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

Upvotes: 0

Akash Shah
Akash Shah

Reputation: 616

in javaDoc

The field that owns the relationship. Required unless the relationship is unidirectional.

using targetEntity=price.class

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

or using mappedby=price

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

   @Entity("Price)
    class Price{
}

Upvotes: 0

ZhenyaM
ZhenyaM

Reputation: 686

Problem in fact, that you didn't provide other mapping for entities. How would hibernate identify that Price related to PastPrice? Hibernate couldn't (but I'm not sure) store array of related ids in Price.

By default, if you want just 2 tables you need to add field in Price:

@ManyToOne(...)
private PastPrice pastPrice;

In this case, in table Price hibernate generate colymn with id of 'parent' price. Thus, for current mapping 2 tables would be enough.

It would be work something like:

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

Upvotes: 0

Related Questions