[Hibernate-JIRA] Created: (HHH-5251) NativeSQLQueryReturn impls pre-cache a final hashcode based on non-final fields
by Steve Ebersole (JIRA)
NativeSQLQueryReturn impls pre-cache a final hashcode based on non-final fields
--------------------------------------------------------------------------------
Key: HHH-5251
URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-5251
Project: Hibernate Core
Issue Type: Improvement
Components: core
Reporter: Steve Ebersole
Assignee: Steve Ebersole
Fix For: 3.6, 3.5.x
For example, code such as
{code}
public class NativeSQLQueryScalarReturn implements NativeSQLQueryReturn {
private Type type;
private String columnAlias;
private final int hashCode;
public NativeSQLQueryScalarReturn(String alias, Type type) {
this.type = type;
this.columnAlias = alias;
this.hashCode = determineHashCode();
}
...
private int determineHashCode() {
int result = type != null ? type.hashCode() : 0;
result = 31 * result + ( getClass().getName().hashCode() );
result = 31 * result + ( columnAlias != null ? columnAlias.hashCode() : 0 );
return result;
}
public int hashCode() {
return hashCode;
}
}
{code}
should really read as such (for correctness):
{code}
public class NativeSQLQueryScalarReturn implements NativeSQLQueryReturn {
private final Type type;
private final String columnAlias;
private final int hashCode;
public NativeSQLQueryScalarReturn(String alias, Type type) {
this.type = type;
this.columnAlias = alias;
this.hashCode = determineHashCode();
}
...
private int determineHashCode() {
int result = type != null ? type.hashCode() : 0;
result = 31 * result + ( getClass().getName().hashCode() );
result = 31 * result + ( columnAlias != null ? columnAlias.hashCode() : 0 );
return result;
}
public int hashCode() {
return hashCode;
}
}
{code}
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://opensource.atlassian.com/projects/hibernate/secure/Administrators....
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
14 years, 5 months
[Hibernate-JIRA] Created: (EJB-225) EntityManager.find infinite loop related to ANN-381
by John Schneider (JIRA)
EntityManager.find infinite loop related to ANN-381
---------------------------------------------------
Key: EJB-225
URL: http://opensource.atlassian.com/projects/hibernate/browse/EJB-225
Project: Hibernate Entity Manager
Type: Bug
Environment: Hibernate Annotations 3.2.0.cr2
Hibernate EntityManager 3.2.0.cr2
Hibernate Core 3.2.0.cr4
Reporter: John Schneider
Attachments: Test.zip
I've tested the fix for ANN-381 and found that the improvement is not working correctly with the Entity Manager, specifically the find method. When calling the find method on a OneToMany collection mapped by a field in a primary key class, the Entity manager goes into an infinite loop of selecting records.
Please note that a workaround is to replace the entity managers find method with a query, such as this:
Query query = entityManager.createQuery("select c from Card c where c.id = :id");
query.setParameter("id", id);
return (Card) query.getSingleResult();
However, this workaround doesn't work if you have other entities that relate to something like the Card entity, shown below. I'll expand on the example code from ANN-381 to show the problem of infinite looping when trying to load the related collection.
@Entity
public class Card implements Serializable {
@Id
private String id;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "primaryKey.card")
private Set<CardField> fields;
public Card(String id) {
this();
this.id = id;
}
Card() {
fields = new HashSet<CardField>();
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public void addField(Card card, Key key) {
fields.add(new CardField(card, key));
}
}
@Entity
public class CardField implements Serializable {
@EmbeddedId
private PrimaryKey primaryKey;
CardField(Card card, Key key) {
this.primaryKey = new PrimaryKey(card, key);
}
CardField() {
}
}
@Embeddable
public class PrimaryKey implements Serializable {
@ManyToOne(optional = false)
private Card card;
@ManyToOne(optional = false)
private Key key;
public PrimaryKey(Card card, Key key) {
this.card = card;
this.key = key;
}
PrimaryKey() {}
}
@Entity
public class Key implements Serializable {
@Id
private String id;
public Key(String id) {
this.id = id;
}
Key() {
}
}
>From what I can tell, this maps fine with the correct Hibernate libs and JBoss EJB Embeddable Alpha 9. However, the Entity Manager must be creating bad query code or something with similar results to having bad queries. I've testing with the following DAO:
@Stateless
public class CardDAOBean implements CardDAOLocal {
@PersistenceContext
private EntityManager entityManager;
public void createCard(Card card) {
entityManager.persist(card);
}
public Card findCard(String id) {
return entityManager.find(Card.class, id);
}
public void createKey(Key key) {
entityManager.persist(key);
}
}
The Test class:
public class EJBTest {
private Card card;
private Key key;
public static void main(String[] args) {
TestRunner.run(suite());
}
public static junit.framework.Test suite() {
TestSuite suite = new TestSuite("Test for ANN-381");
suite.addTest(new JUnit4TestAdapter(EJBTest.class));
// setup test so that embedded JBoss is started/stopped once for all
// tests here.
TestSetup wrapper = new TestSetup(suite) {
protected void setUp() {
startupEmbeddedJboss();
}
protected void tearDown() {
shutdownEmbeddedJboss();
}
};
return wrapper;
}
@Before
public void setup() {
card = new Card("cardId");
key = new Key("keyId");
card.addField(card, key);
}
@Test
public void persist() throws Exception {
InitialContext ctx = getInitialContext();
CardDAOLocal CardDAOLocal = (CardDAOLocal) ctx.lookup("CardDAOBean/local");
CardDAOLocal.createKey(key);
CardDAOLocal.createCard(card);
Card card = CardDAOLocal.findCard(this.card.getId());
assertNotNull(card);
}
private static void startupEmbeddedJboss() {
EJB3StandaloneBootstrap.boot(null);
EJB3StandaloneBootstrap.scanClasspath();
}
private static void shutdownEmbeddedJboss() {
EJB3StandaloneBootstrap.shutdown();
}
public static InitialContext getInitialContext() throws Exception {
Hashtable properties = getInitialContextProperties();
return new InitialContext(properties);
}
private static Hashtable getInitialContextProperties() {
Hashtable<String, String> props = new Hashtable<String, String>();
props.put("java.naming.factory.initial",
"org.jnp.interfaces.LocalOnlyContextFactory");
props.put("java.naming.factory.url.pkgs",
"org.jboss.naming:org.jnp.interfaces");
return props;
}
}
Here's some relevant debugging output:
Row insert: update CardField set card_id=? where card_id=? and key_id=?
Row delete: update CardField set card_id=null where card_id=? and card_id=? and key_id=?
One-shot delete: update CardField set card_id=null where card_id=?
Static select for entity entity.CardField: select cardfield0_.card_id as card2_1_0_, cardfield0_.key_id as key1_1_0_ from CardField cardfield0_ where cardfield0_.card_id=? and cardfield0_.key_id=?
Static select for action ACTION_MERGE on entity entity.CardField: select cardfield0_.card_id as card2_1_0_, cardfield0_.key_id as key1_1_0_ from CardField cardfield0_ where cardfield0_.card_id=? and cardfield0_.key_id=?
Static select for action ACTION_REFRESH on entity entity.CardField: select cardfield0_.card_id as card2_1_0_, cardfield0_.key_id as key1_1_0_ from CardField cardfield0_ where cardfield0_.card_id=? and cardfield0_.key_id=?
Static select for entity entity.Card: select card0_.id as id0_1_, fields1_.card_id as card2_3_, fields1_.key_id as key1_3_, fields1_.card_id as card2_1_0_, fields1_.key_id as key1_1_0_ from Card card0_ left outer join CardField fields1_ on card0_.id=fields1_.card_id where card0_.id=?
Static select for entity entity.Card: select card0_.id as id0_1_, fields1_.card_id as card2_3_, fields1_.key_id as key1_3_, fields1_.card_id as card2_1_0_, fields1_.key_id as key1_1_0_ from Card card0_ left outer join CardField fields1_ on card0_.id=fields1_.card_id where card0_.id=?
Static select for entity entity.Card: select card0_.id as id0_0_ from Card card0_ where card0_.id=?
Static select for entity entity.Card: select card0_.id as id0_0_ from Card card0_ where card0_.id=?
Static select for entity entity.Card: select card0_.id as id0_0_ from Card card0_ where card0_.id=?
Static select for action ACTION_MERGE on entity entity.Card: select card0_.id as id0_1_, fields1_.card_id as card2_3_, fields1_.key_id as key1_3_, fields1_.card_id as card2_1_0_, fields1_.key_id as key1_1_0_ from Card card0_ left outer join CardField fields1_ on card0_.id=fields1_.card_id where card0_.id=?
Static select for action ACTION_REFRESH on entity entity.Card: select card0_.id as id0_1_, fields1_.card_id as card2_3_, fields1_.key_id as key1_3_, fields1_.card_id as card2_1_0_, fields1_.key_id as key1_1_0_ from Card card0_ left outer join CardField fields1_ on card0_.id=fields1_.card_id where card0_.id=?
Static select for entity entity.Key: select key0_.id as id2_0_ from Key key0_ where key0_.id=?
Static select for entity entity.Key: select key0_.id as id2_0_ from Key key0_ where key0_.id=?
Static select for entity entity.Key: select key0_.id as id2_0_ from Key key0_ where key0_.id=?
Static select for entity entity.Key: select key0_.id as id2_0_ from Key key0_ where key0_.id=?
Static select for entity entity.Key: select key0_.id as id2_0_ from Key key0_ where key0_.id=?
Static select for action ACTION_MERGE on entity entity.Key: select key0_.id as id2_0_ from Key key0_ where key0_.id=?
Static select for action ACTION_REFRESH on entity entity.Key: select key0_.id as id2_0_ from Key key0_ where key0_.id=?
Static select for one-to-many entity.Card.fields: select fields0_.card_id as card2_1_, fields0_.key_id as key1_1_, fields0_.card_id as card2_1_0_, fields0_.key_id as key1_1_0_ from CardField fields0_ where fields0_.card_id=?
When I call the findCard method in my EJB, the entity manager keeps looping through the select process several hundred times, and then dies from a stack overflow.
Here's a sample of looping:
DEBUG 17-09 21:17:18,328 (Log4JLogger.java:debug:84) -select card0_.id as id0_1_, fields1_.card_id as card2_3_, fields1_.key_id as key1_3_, fields1_.card_id as card2_1_0_, fields1_.key_id as key1_1_0_ from Card card0_ left outer join CardField fields1_ on card0_.id=fields1_.card_id where card0_.id=?
DEBUG 17-09 21:17:18,343 (Log4JLogger.java:debug:84) -about to open ResultSet (open ResultSets: 0, globally: 0)
DEBUG 17-09 21:17:18,343 (Log4JLogger.java:debug:84) -loading entity: [entity.Card#cardId]
DEBUG 17-09 21:17:18,359 (Log4JLogger.java:debug:84) -about to open PreparedStatement (open PreparedStatements: 1, globally: 1)
DEBUG 17-09 21:17:18,359 (Log4JLogger.java:debug:84) -select card0_.id as id0_1_, fields1_.card_id as card2_3_, fields1_.key_id as key1_3_, fields1_.card_id as card2_1_0_, fields1_.key_id as key1_1_0_ from Card card0_ left outer join CardField fields1_ on card0_.id=fields1_.card_id where card0_.id=?
DEBUG 17-09 21:17:18,359 (Log4JLogger.java:debug:84) -about to open ResultSet (open ResultSets: 1, globally: 1)
DEBUG 17-09 21:17:18,359 (Log4JLogger.java:debug:84) -loading entity: [entity.Card#cardId]
DEBUG 17-09 21:17:18,359 (Log4JLogger.java:debug:84) -about to open PreparedStatement (open PreparedStatements: 2, globally: 2)
DEBUG 17-09 21:17:18,359 (Log4JLogger.java:debug:84) -select card0_.id as id0_1_, fields1_.card_id as card2_3_, fields1_.key_id as key1_3_, fields1_.card_id as card2_1_0_, fields1_.key_id as key1_1_0_ from Card card0_ left outer join CardField fields1_ on card0_.id=fields1_.card_id where card0_.id=?
DEBUG 17-09 21:17:18,359 (Log4JLogger.java:debug:84) -about to open ResultSet (open ResultSets: 2, globally: 2)
DEBUG 17-09 21:17:18,359 (Log4JLogger.java:debug:84) -loading entity: [entity.Card#cardId]
DEBUG 17-09 21:17:18,359 (Log4JLogger.java:debug:84) -about to open PreparedStatement (open PreparedStatements: 3, globally: 3)
DEBUG 17-09 21:17:18,375 (Log4JLogger.java:debug:84) -select card0_.id as id0_1_, fields1_.card_id as card2_3_, fields1_.key_id as key1_3_, fields1_.card_id as card2_1_0_, fields1_.key_id as key1_1_0_ from Card card0_ left outer join CardField fields1_ on card0_.id=fields1_.card_id where card0_.id=?
DEBUG 17-09 21:17:18,375 (Log4JLogger.java:debug:84) -about to open ResultSet (open ResultSets: 3, globally: 3)
DEBUG 17-09 21:17:18,375 (Log4JLogger.java:debug:84) -loading entity: [entity.Card#cardId]
DEBUG 17-09 21:17:18,375 (Log4JLogger.java:debug:84) -about to open PreparedStatement (open PreparedStatements: 4, globally: 4)
DEBUG 17-09 21:17:18,375 (Log4JLogger.java:debug:84) -select card0_.id as id0_1_, fields1_.card_id as card2_3_, fields1_.key_id as key1_3_, fields1_.card_id as card2_1_0_, fields1_.key_id as key1_1_0_ from Card card0_ left outer join CardField fields1_ on card0_.id=fields1_.card_id where card0_.id=?
DEBUG 17-09 21:17:18,375 (Log4JLogger.java:debug:84) -about to open ResultSet (open ResultSets: 4, globally: 4)
DEBUG 17-09 21:17:18,375 (Log4JLogger.java:debug:84) -loading entity: [entity.Card#cardId]
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
http://opensource.atlassian.com/projects/hibernate/secure/Administrators....
-
For more information on JIRA, see:
http://www.atlassian.com/software/jira
14 years, 5 months