Reputation: 61
I was wondering if it was possible to return a List of persistent entities in hibernate and only load selected records into a collection for each entity in that list. For example, I have a list of about 5000 stock tickers, and each one has a collection of price records. So I don't want to add all of the price records into each of the tickers, just maybe the last 350 or so. I'm not exactly sure how to do this, but all my attempts have come up with ClassCastExceptions, or Query errors.
Here is my Ticker class/configuration:
@Entity
@Table(name="tickers",
uniqueConstraints =
@UniqueConstraint(columnNames={"symbol"}))
@SecondaryTable(name="groups")
public class Ticker implements Persistable{
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="ticker_id", nullable=false, unique=true, length=11)
@Type(type="integer")
public int getTickerId() {
return this.tickerId;
}
public void setTickerId(int tickerId) {
this.tickerId = tickerId;
}
private int tickerId;
@Column(name="name", nullable=false, unique=false, length=60)
@Type(type="java.lang.String")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private String name;
@Column(name="symbol", nullable=false, unique=true, length=10)
@Type(type="java.lang.String")
@NaturalId
public String getSymbol() {
return symbol;
}
public void setSymbol(String symbol) {
this.symbol = symbol;
}
private String symbol;
@Column(name="type", nullable=false, unique=false, length=20)
@Enumerated(value=EnumType.STRING)
public TickerType getTickerType() {
return tickerType;
}
public void setTickerType(TickerType tickerType) {
this.tickerType = tickerType;
}
private TickerType tickerType;
@Column(name="supergroup", nullable=true, unique=false, length=100, table="groups")
@Enumerated(value=EnumType.STRING)
public TickerSuperGroup getTickerSuperGroup() {
return tickerSuperGroup;
}
public void setTickerSuperGroup(TickerSuperGroup tickerSuperGroup) {
this.tickerSuperGroup = tickerSuperGroup;
}
private TickerSuperGroup tickerSuperGroup;
@Column(name="industrygroup", nullable=true, unique=false, length=100, table="groups")
@Enumerated(value=EnumType.STRING)
public TickerGroup getTickerGroup() {
return tickerGroup;
}
public void setTickerGroup(TickerGroup tickerGroup) {
this.tickerGroup = tickerGroup;
}
private TickerGroup tickerGroup;
@Column(name="subgroup", nullable=true, unique=false, length=100, table="groups")
@Enumerated(value=EnumType.STRING)
public TickerSubGroup getTickerSubGroup() {
return tickerSubGroup;
}
public void setTickerSubGroup(TickerSubGroup tickerSubGroup) {
this.tickerSubGroup = tickerSubGroup;
}
private TickerSubGroup tickerSubGroup;
@OneToMany(mappedBy="ticker", targetEntity=com.lisria.model.historical.PriceRecord.class,
cascade=CascadeType.ALL, orphanRemoval=true, fetch=FetchType.LAZY)
@OrderBy("trade_date")
private List<PriceRecord> getPriceRecords() {
return priceRecords;
}
@SuppressWarnings("unused")
private void setPriceRecords(List<PriceRecord> priceRecords) {
this.priceRecords = priceRecords;
}
private List<PriceRecord> priceRecords = new ArrayList<PriceRecord>();
And then a method to return a list of Tickers...
@Override
public List<Ticker> getListOfTickers(Date startDate) {
Session session = sessionFactory.openSession();
session.beginTransaction();
@SuppressWarnings("unchecked")
List<Ticker> tickers =
session.createQuery("from Ticker as tickers "
+ "left join tickers.priceRecords as prices "
+ "with prices.tradeDate >=" + startDate.toString()).list();
session.getTransaction().commit();
session.close();
return tickers;
}
The getListOfTickers(Date startDate) method throws a ClassCastException when referencing objects in the list, because a list of Ticker objects is not returned by the query. Of course, the easist way to get tickers is with:
session.createQuery("from Ticker").list()
But this leads to LazyInitialization errors, while changing the FetchType to eager, or even initializing the collection leads to loading the WHOLE collection which is exactly what I want to avoid. So, how should I go about approaching this issue, even if I can't get a list of Tickers to iterate through, I can get a list of primary keys with which to load each ticker in the table, but still do not know how to load only a subset of the PriceRecords.
Upvotes: 1
Views: 163
Reputation: 61
So one answer is here:
Strategy to fetch a subset of a collection
Though this is surprisingly hard to find in a search engine, and it couples my class to a hibernate implementation - but I'll live with it for now. Still other answers interest me.
Upvotes: 1