0

I'm trying to pull records in Hibernate using the following Criteria query.

Security result = (Security) getSession().createCriteria(Security.class)
        .add(  Restrictions.eq("symbol", symbol) ).uniqueResult();

The symbol attribute is a unique varchar type (stock symbols), and the symbol parameter is a String.

Normally this works just fine, but whenever the symbol includes a hyphen in the name such as "C-U" I get an AssertionFailure Exception.

Any idea what I'm doing wrong or how to work around?


Some background....

This occurs inside of a long transaction in which I'm storing intra-day stats (current price of stocks pulled from Yahoo) for a ton of stocks (securities) from NYSE and NASDAQ.

By the point this is thrown, a couple hundred securities have made it through the loop. They've been "saved" but the transaction hasn't been committed yet. I cut that off before the buffer (?) is full. Only if and when it comes to a security with a hyphen in the symbol does it throw this exception.

Here's the calling argument....

security = securityDAO.findBySymbol(record[0]);

The full method in SecurityDAO.......

public Security findBySymbol(String symbol){
    log.debug("finding Security by symbol");
    try{

        Security result = 
            (Security) getSession().createCriteria(Security.class)
        .add(  Restrictions.eq("symbol", symbol)).uniqueResult();

        if (result == null)
            return null;

        return result;
    } catch (RuntimeException re) {
        log.error("Failed to find security by symbol.", re);
        throw re;
    }
}

The Exception thrown...

org.hibernate.AssertionFailure: null id in com.securityscanner.hibernate.IntradayStat entry (don't flush the Session after an exception occurs)
at org.hibernate.event.def.DefaultFlushEntityEventListener.checkId(DefaultFlushEntityEventListener.java:78)
at org.hibernate.event.def.DefaultFlushEntityEventListener.getValues(DefaultFlushEntityEventListener.java:187)
at org.hibernate.event.def.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:143)
at org.hibernate.event.def.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:219)
at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:99)
at org.hibernate.event.def.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:58)
at org.hibernate.impl.SessionImpl.autoFlushIfRequired(SessionImpl.java:997)
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1590)
at org.hibernate.impl.CriteriaImpl.list(CriteriaImpl.java:306)
at org.hibernate.impl.CriteriaImpl.uniqueResult(CriteriaImpl.java:328)
at com.securityscanner.hibernate.SecurityDAO.findBySymbol(SecurityDAO.java:187)
at com.securityscanner.ScanStatsTask.storeCurrentStats(ScanStatsTask.java:196)
at com.securityscanner.ScanStatsTask.run(ScanStatsTask.java:99)
at java.util.TimerThread.mainLoop(Timer.java:512)
at java.util.TimerThread.run(Timer.java:462)

Security extends AbstractSecurity................................

/

**
 * AbstractSecurity entity provides the base persistence definition of the
 * Security entity. @author MyEclipse Persistence Tools
 */

public abstract class AbstractSecurity implements java.io.Serializable {

    // Fields

    private Integer securityId;
    private Exchange exchange;
    private String name;
    private String symbol;
    private String securityType;
    private String description;
    private Boolean skip;
    private Set dailyStats = new HashSet(0);
    private Set intradayStats = new HashSet(0);

    // Constructors

    /** default constructor */
    public AbstractSecurity() {
    }

    /** full constructor */
    public AbstractSecurity(Exchange exchange, String name, String symbol,
            String securityType, String description, Boolean skip,
            Set dailyStats, Set intradayStats) {
        this.exchange = exchange;
        this.name = name;
        this.symbol = symbol;
        this.securityType = securityType;
        this.description = description;
        this.skip = skip;
        this.dailyStats = dailyStats;
        this.intradayStats = intradayStats;
    }

    // Property accessors

    public Integer getSecurityId() {
        return this.securityId;
    }

    public void setSecurityId(Integer securityId) {
        this.securityId = securityId;
    }

    public Exchange getExchange() {
        return this.exchange;
    }

    public void setExchange(Exchange exchange) {
        this.exchange = exchange;
    }

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSymbol() {
        return this.symbol;
    }

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

    public String getSecurityType() {
        return this.securityType;
    }

    public void setSecurityType(String securityType) {
        this.securityType = securityType;
    }

    public String getDescription() {
        return this.description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public Boolean getSkip() {
        return this.skip;
    }

    public void setSkip(Boolean skip) {
        this.skip = skip;
    }

    public Set getDailyStats() {
        return this.dailyStats;
    }

    public void setDailyStats(Set dailyStats) {
        this.dailyStats = dailyStats;
    }

    public Set getIntradayStats() {
        return this.intradayStats;
    }

    public void setIntradayStats(Set intradayStats) {
        this.intradayStats = intradayStats;
    }

}
talonmies
  • 70,661
  • 34
  • 192
  • 269

1 Answers1

1

Patrick, the error is not in the select, but somewhere before.

Hibernate keeps a list of all the updated or created objects, when you flush the session or perform any other operation that forces a flush, such as a select, it saves all the dirty objects to the database.

From the stack trace, it looks like you have saved / updated a new instance of IntradayStat without an id and hibernate is expecting one.

Augusto
  • 28,839
  • 5
  • 58
  • 88
  • Yeah, as I looked back through I had the same suspicion. I'll look into it and report back. Thanks for your help! =) – Patrick Jackson Sep 18 '12 at 00:52
  • Yup. Looks like that's exactly what happened. There were some invalid timestamps getting through that happened to coincide with securities with hyphenated symbols. When they were flushed, the DB refused to insert them and assign an ID. I tightened up validation and transaction handling, and the run is now completing successfully. Thanks again! – Patrick Jackson Sep 18 '12 at 02:27