hibernate restrictions on string with hyphen throws assertionfailure exception
-
02-07-2021 - |
题
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;
}
}
解决方案
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.