blob: 7522f854592ee5929b43fb8644c637f13311da16 [file] [log] [blame]
/*
* Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
// Contributors:
// Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.testing.tests.jpa.inheritance;
import java.util.Collection;
import org.eclipse.persistence.annotations.BatchFetchType;
import org.eclipse.persistence.config.QueryHints;
import org.eclipse.persistence.expressions.ExpressionBuilder;
import org.eclipse.persistence.queries.UpdateAllQuery;
import org.eclipse.persistence.testing.framework.junit.JUnitTestCase;
import org.eclipse.persistence.testing.models.jpa.inheritance.InheritanceTableCreator;
import org.eclipse.persistence.jpa.JpaEntityManager;
import org.eclipse.persistence.testing.models.jpa.inheritance.Assassin;
import org.eclipse.persistence.testing.models.jpa.inheritance.Bomb;
import org.eclipse.persistence.testing.models.jpa.inheritance.ContractedPersonel;
import org.eclipse.persistence.testing.models.jpa.inheritance.DirectElimination;
import org.eclipse.persistence.testing.models.jpa.inheritance.DirectWeapon;
import org.eclipse.persistence.testing.models.jpa.inheritance.Elimination;
import org.eclipse.persistence.testing.models.jpa.inheritance.EliminationPK;
import org.eclipse.persistence.testing.models.jpa.inheritance.Gun;
import org.eclipse.persistence.testing.models.jpa.inheritance.IndirectElimination;
import org.eclipse.persistence.testing.models.jpa.inheritance.IndirectWeapon;
import org.eclipse.persistence.testing.models.jpa.inheritance.SocialClub;
import org.eclipse.persistence.testing.models.jpa.inheritance.SpecialAssassin;
import org.eclipse.persistence.testing.models.jpa.inheritance.Weapon;
import junit.framework.Test;
import junit.framework.TestSuite;
import jakarta.persistence.LockModeType;
import jakarta.persistence.OptimisticLockException;
import jakarta.persistence.PersistenceException;
import jakarta.persistence.Query;
import jakarta.persistence.EntityManager;
public class TablePerClassInheritanceJUnitTest extends JUnitTestCase {
private static Integer assassinId;
private static Integer specialAssassinId;
private static Integer socialClub1Id;
private static Integer socialClub2Id;
private static Integer socialClub3Id;
private static Integer gunSerialNumber;
private static EliminationPK directEliminationPK;
private static EliminationPK indirectEliminationPK;
public TablePerClassInheritanceJUnitTest() {
super();
}
public TablePerClassInheritanceJUnitTest(String name) {
super(name);
}
@Override
public void setUp() {
super.setUp();
clearCache();
}
public static Test suite() {
TestSuite suite = new TestSuite();
suite.setName("TablePerClassInheritanceJUnitTestSuite");
suite.addTest(new TablePerClassInheritanceJUnitTest("testSetup"));
suite.addTest(new TablePerClassInheritanceJUnitTest("testCreateAssassinWithGun"));
suite.addTest(new TablePerClassInheritanceJUnitTest("testValidateAssassinWithGun"));
suite.addTest(new TablePerClassInheritanceJUnitTest("testValidateGunToAssassin"));
suite.addTest(new TablePerClassInheritanceJUnitTest("testAddDirectElimination"));
suite.addTest(new TablePerClassInheritanceJUnitTest("testValidateDirectElimination"));
suite.addTest(new TablePerClassInheritanceJUnitTest("testAddIndirectElimination"));
suite.addTest(new TablePerClassInheritanceJUnitTest("testValidateIndirectElimination"));
suite.addTest(new TablePerClassInheritanceJUnitTest("testValidateAssassinWithBombAndEliminations"));
suite.addTest(new TablePerClassInheritanceJUnitTest("testNamedQueryFindAllWeapons"));
suite.addTest(new TablePerClassInheritanceJUnitTest("testNamedQueryFindAllWeaponsWhereDescriptionContainsSniper"));
suite.addTest(new TablePerClassInheritanceJUnitTest("testCreateNewSocialClubsWithMembers"));
suite.addTest(new TablePerClassInheritanceJUnitTest("testBatchFindAllWeapons"));
suite.addTest(new TablePerClassInheritanceJUnitTest("testValidateSocialClub1Members"));
suite.addTest(new TablePerClassInheritanceJUnitTest("testValidateSocialClub2Members"));
suite.addTest(new TablePerClassInheritanceJUnitTest("testValidateSocialClub3Members"));
suite.addTest(new TablePerClassInheritanceJUnitTest("testAssassinOptimisticLocking"));
suite.addTest(new TablePerClassInheritanceJUnitTest("testSpecialAssassinOptimisticLocking"));
suite.addTest(new TablePerClassInheritanceJUnitTest("testAssassinOptimisticLockingUsingEntityManagerAPI"));
suite.addTest(new TablePerClassInheritanceJUnitTest("testGunOptimisticLocking"));
suite.addTest(new TablePerClassInheritanceJUnitTest("testUpdateAllQuery"));
return suite;
}
/**
* The setup is done as a test, both to record its failure, and to allow execution in the server.
*/
public void testSetup() {
new InheritanceTableCreator().replaceTables(JUnitTestCase.getServerSession());
clearCache();
}
public void testCreateAssassinWithGun() {
EntityManager em = createEntityManager();
Assassin assassin = null;
try {
beginTransaction(em);
assassin = new Assassin();
assassin.setName("Assassin1");
assassin.getNicknames().add("Bonny");
assassin.getNicknames().add("Clyde");
Gun gun = new Gun();
gun.setCaliber(50);
gun.setDescription("Sniper rifle");
gun.setModel("9-112");
assassin.setWeapon(gun);
em.persist(assassin);
assassinId = assassin.getId();
gunSerialNumber = gun.getSerialNumber();
commitTransaction(em);
} catch (Exception exception) {
exception.printStackTrace();
fail("Error persisting new assassin: " + exception.getMessage());
} finally {
closeEntityManager(em);
}
verifyObjectInCacheAndDatabase(assassin);
}
public void testValidateAssassinWithGun() {
EntityManager em = createEntityManager();
Assassin assassin = em.find(Assassin.class, assassinId);
assertNotNull("The assassin could not be read back.", assassin);
Weapon weapon = assassin.getWeapon();
assertNotNull("The assassin's weapon was null", weapon);
assertTrue("The assassin's weapon was not a direct weapon", weapon.isDirectWeapon());
assertTrue("The assassin's weapon was not a gun", ((DirectWeapon) weapon).isGun());
closeEntityManager(em);
}
public void testValidateGunToAssassin() {
EntityManager em = createEntityManager();
Gun gun = em.find(Gun.class, gunSerialNumber);
assertNotNull("The gun could not be read back.", gun);
Assassin assassin = gun.getAssassin();
assertNotNull("The gun's assassin was null", assassin);
assertTrue("The gun is currently not assigned to the correct assassin", assassin.getId().equals(assassinId));
closeEntityManager(em);
}
public void testAddDirectElimination() {
EntityManager em = createEntityManager();
DirectElimination directElimination = null;
try {
beginTransaction(em);
Assassin assassin = em.find(Assassin.class, assassinId);
// Assassin already has a gun, therefore, correct weapon already set
// for a direct elimination.
directElimination = new DirectElimination();
directElimination.setId(Long.valueOf(System.currentTimeMillis()).intValue());
directElimination.setName("Joe Smuck");
directElimination.setDescription("Because he has a big mouth");
directElimination.setAssassin(assassin);
em.persist(directElimination);
directEliminationPK = directElimination.getPK();
assassin.getEliminations().add(directElimination);
commitTransaction(em);
} catch (Exception e) {
fail("Error adding new direct elimination: " + e.getMessage());
} finally {
closeEntityManager(em);
}
verifyObjectInCacheAndDatabase(directElimination);
}
public void testValidateDirectElimination() {
EntityManager em = createEntityManager();
Elimination directElimination = em.find(Elimination.class, directEliminationPK);
assertNotNull("The direct elimination could not be read back.", directElimination);
assertTrue("The elimination was not a direct elimination", directElimination.isDirectElimination());
// Validate the weapon that was used for the direct elimination.
DirectWeapon weapon = ((DirectElimination) directElimination).getDirectWeapon();
assertNotNull("The direct elimination's weapon was null", weapon);
assertTrue("The direct elimination's weapon was not a direct weapon", weapon.isDirectWeapon());
assertTrue("The direct elimination's weapon was not a gun", weapon.isGun());
closeEntityManager(em);
}
public void testAddIndirectElimination() {
EntityManager em = createEntityManager();
IndirectElimination indirectElimination = null;
try {
beginTransaction(em);
Assassin assassin = em.find(Assassin.class, assassinId);
Bomb bomb = new Bomb();
bomb.setBombType(Bomb.BOMBTYPE.DIRTY);
bomb.setDescription("Nasty blasty");
em.persist(bomb);
// Must set the correct weapon before an elimination.
assassin.setWeapon(bomb);
indirectElimination = new IndirectElimination();
indirectElimination.setId(Long.valueOf(System.currentTimeMillis()).intValue());
indirectElimination.setName("Jill Smuck");
indirectElimination.setDescription("Because she has a big mouth");
indirectElimination.setAssassin(assassin);
em.persist(indirectElimination);
indirectEliminationPK = indirectElimination.getPK();
assassin.getEliminations().add(indirectElimination);
commitTransaction(em);
} catch (Exception e) {
fail("Error adding new indirect elimination: " + e.getMessage());
} finally {
closeEntityManager(em);
}
verifyObjectInCacheAndDatabase(indirectElimination);
}
public void testValidateIndirectElimination() {
EntityManager em = createEntityManager();
Elimination indirectElimination = em.find(Elimination.class, indirectEliminationPK);
assertNotNull("The indirect elimination could not be read back.", indirectElimination);
assertTrue("The elimination was not an idirect elimination", indirectElimination.isIndirectElimination());
// Validate the weapon that was used for the direct elimination.
IndirectWeapon weapon = ((IndirectElimination) indirectElimination).getIndirectWeapon();
assertNotNull("The indirect elimination's weapon was null", weapon);
assertTrue("The indirect elimination's weapon was not an idirect weapon", weapon.isIndirectWeapon());
assertTrue("The indirect elimination's weapon was not a bomb", weapon.isBomb());
closeEntityManager(em);
}
public void testValidateAssassinWithBombAndEliminations() {
EntityManager em = createEntityManager();
Assassin assassin = em.find(Assassin.class, assassinId);
assertNotNull("The assassin could not be read back.", assassin);
assassin.getEliminations();
assertFalse("The assassin didn't have any eliminations", assassin.getEliminations().isEmpty());
Weapon weapon = assassin.getWeapon();
assertNotNull("The assassin's weapon was null", weapon);
assertTrue("The assassin's weapon was not an indirect weapon", weapon.isIndirectWeapon());
assertTrue("The assassin's weapon was not a bomb", ((IndirectWeapon) weapon).isBomb());
closeEntityManager(em);
}
// At this point no Weapon objects have been created only only real weapons.
// So if the query returns an empty collection, something is not working.
// We have create a gun and a bomb at this point ...
public void testNamedQueryFindAllWeapons() {
EntityManager em = createEntityManager();
try {
Query query = em.createNamedQuery("findAllWeapons");
Collection<Weapon> weapons = query.getResultList();
assertFalse("No weapons were returned", weapons.isEmpty());
assertTrue("Expected weapon count of 2 not returned", weapons.size() == 2);
} finally {
closeEntityManager(em);
}
}
// At this point no Weapon objects have been created only only real weapons.
// So if the query returns an empty collection, something is not working.
// We have create a gun and a bomb at this point ...
public void testBatchFindAllWeapons() {
EntityManager em = createEntityManager();
try {
Query query = em.createQuery("Select w from Weapon w");
query.setHint(QueryHints.BATCH, "w.assassin");
query.setHint(QueryHints.BATCH_TYPE, BatchFetchType.IN);
Collection<Weapon> weapons = query.getResultList();
for (Weapon weapon : weapons) {
weapon.getAssassin();
}
assertFalse("No weapons were returned", weapons.isEmpty());
assertTrue("Expected weapon count of 2 not returned", weapons.size() == 2);
clearCache();
em.clear();
query = em.createQuery("Select w from Weapon w");
query.setHint(QueryHints.BATCH, "w.assassin");
query.setHint(QueryHints.BATCH_TYPE, BatchFetchType.EXISTS);
weapons = query.getResultList();
for (Weapon weapon : weapons) {
weapon.getAssassin();
}
assertFalse("No weapons were returned", weapons.isEmpty());
assertTrue("Expected weapon count of 2 not returned", weapons.size() == 2);
clearCache();
em.clear();
query = em.createQuery("Select w from Weapon w");
query.setHint(QueryHints.BATCH, "w.assassin");
query.setHint(QueryHints.BATCH_TYPE, BatchFetchType.JOIN);
weapons = query.getResultList();
for (Weapon weapon : weapons) {
weapon.getAssassin();
}
assertFalse("No weapons were returned", weapons.isEmpty());
assertTrue("Expected weapon count of 2 not returned", weapons.size() == 2);
clearCache();
em.clear();
query = em.createQuery("Select s from SocialClub s");
query.setHint(QueryHints.BATCH, "s.members");
query.setHint(QueryHints.BATCH_TYPE, BatchFetchType.IN);
Collection<SocialClub> clubs = query.getResultList();
for (SocialClub club : clubs) {
club.getMembers().size();
}
clearCache();
em.clear();
query = em.createQuery("Select s from SocialClub s");
query.setHint(QueryHints.BATCH, "s.members");
query.setHint(QueryHints.BATCH_TYPE, BatchFetchType.JOIN);
clubs = query.getResultList();
for (SocialClub club : clubs) {
club.getMembers().size();
}
clearCache();
em.clear();
query = em.createQuery("Select s from SocialClub s");
query.setHint(QueryHints.BATCH, "s.members");
query.setHint(QueryHints.BATCH_TYPE, BatchFetchType.EXISTS);
clubs = query.getResultList();
for (SocialClub club : clubs) {
club.getMembers().size();
}
} finally {
closeEntityManager(em);
}
}
// At this point no Weapon objects have been created only only real weapons.
// So if the query returns an empty collection, something is not working.
// We have create a gun and a bomb at this point, and the gun is a sniper rifle.
public void testNamedQueryFindAllWeaponsWhereDescriptionContainsSniper() {
EntityManager em = createEntityManager();
try {
Query query = em.createNamedQuery("findAllWeaponsContainingDescription");
query.setParameter("description", "Sniper%");
Collection<Weapon> weapons = query.getResultList();
assertFalse("No weapons were returned", weapons.isEmpty());
assertTrue("Expected weapon count of 1 not returned", weapons.size() == 1);
} catch (Exception e) {
e.printStackTrace();
fail("Error issuing find all weapons query: " + e.getMessage());
} finally {
closeEntityManager(em);
}
}
// Maybe test that setting this flag does not cause an error. Internally
// it gets ignored.
// ((ObjectLevelReadQuery)((EJBQueryImpl) query).getDatabaseQuery()).setShouldOuterJoinSubclasses(true);
public void testCreateNewSocialClubsWithMembers() {
EntityManager em = createEntityManager();
SocialClub socialClub1 = null;
SocialClub socialClub2 = null;
SocialClub socialClub3 = null;
try {
beginTransaction(em);
// Create some new clubs.
socialClub1 = new SocialClub();
socialClub1.setName("Jimmy's my name and killing is my game!");
em.persist(socialClub1);
socialClub1Id = socialClub1.getId();
socialClub2 = new SocialClub();
socialClub2.setName("Sharp shooting");
em.persist(socialClub2);
socialClub2Id = socialClub2.getId();
socialClub3 = new SocialClub();
socialClub3.setName("Precision explosions");
em.persist(socialClub3);
socialClub3Id = socialClub3.getId();
// Create a couple new characters and add them to various clubs.
ContractedPersonel contractedPersonel = new ContractedPersonel();
contractedPersonel.setName("Hired Goon");
em.persist(contractedPersonel);
SpecialAssassin specialAssassin = new SpecialAssassin();
specialAssassin.setName("IED Expert");
em.persist(specialAssassin);
specialAssassinId = specialAssassin.getId();
Assassin assassin = em.find(Assassin.class, assassinId);
socialClub1.addMember(assassin);
socialClub1.addMember(contractedPersonel);
socialClub1.addMember(specialAssassin);
socialClub2.addMember(assassin);
socialClub2.addMember(contractedPersonel);
socialClub3.addMember(contractedPersonel);
socialClub3.addMember(specialAssassin);
commitTransaction(em);
} finally {
closeEntityManager(em);
}
verifyObjectInCacheAndDatabase(socialClub1);
verifyObjectInCacheAndDatabase(socialClub2);
verifyObjectInCacheAndDatabase(socialClub3);
}
public void testValidateSocialClub1Members() {
EntityManager em = createEntityManager();
SocialClub socialClub1 = createEntityManager().find(SocialClub.class, socialClub1Id);
assertNotNull("The social club 1 could not be read back.", socialClub1);
assertFalse("The member list was empty", socialClub1.getMembers().isEmpty());
assertTrue("The member count was not the expected 3", socialClub1.getMembers().size() == 3);
closeEntityManager(em);
}
public void testValidateSocialClub2Members() {
EntityManager em = createEntityManager();
SocialClub socialClub2 = createEntityManager().find(SocialClub.class, socialClub2Id);
assertNotNull("The social club 1 could not be read back.", socialClub2);
assertFalse("The member list was empty", socialClub2.getMembers().isEmpty());
assertTrue("The member count was not the expected 2", socialClub2.getMembers().size() == 2);
closeEntityManager(em);
}
public void testValidateSocialClub3Members() {
EntityManager em = createEntityManager();
SocialClub socialClub3 = createEntityManager().find(SocialClub.class, socialClub3Id);
assertNotNull("The social club 1 could not be read back.", socialClub3);
assertFalse("The member list was empty", socialClub3.getMembers().isEmpty());
assertTrue("The member count was not the expected 2", socialClub3.getMembers().size() == 2);
closeEntityManager(em);
}
// Tested for an Assassin and a SpecialAssasin
protected void optimisticLockTestOnAssassin(Integer id) {
// Cannot create parallel entity managers in the server.
if (! isOnServer()) {
EntityManager em1 = createEntityManager();
EntityManager em2 = createEntityManager();
em1.getTransaction().begin();
em2.getTransaction().begin();
RuntimeException caughtException = null;
try {
Assassin assassin1 = em1.find(Assassin.class, id);
Assassin assassin2 = em2.find(Assassin.class, id);
assassin1.setName("Geezer");
assassin2.setName("Guyzer");
em1.getTransaction().commit();
em2.getTransaction().commit();
em1.close();
em2.close();
} catch (RuntimeException e) {
if (em1.getTransaction().isActive()){
em1.getTransaction().rollback();
}
if (em2.getTransaction().isActive()){
em2.getTransaction().rollback();
}
if (e.getCause() instanceof jakarta.persistence.OptimisticLockException) {
caughtException = e;
} else {
throw e;
}
} finally {
em1.close();
em2.close();
}
if (caughtException == null) {
fail("Optimistic lock exception was not thrown.");
}
}
}
public void testAssassinOptimisticLocking() {
optimisticLockTestOnAssassin(assassinId);
}
// Just being thorough ... special assassin uses a difference column
// for versioning through an attribute override, but if it didn't work
// we would have known long before now.
public void testSpecialAssassinOptimisticLocking() {
optimisticLockTestOnAssassin(specialAssassinId);
}
public void testAssassinOptimisticLockingUsingEntityManagerAPI() {
// Cannot create parallel entity managers in the server.
if (! isOnServer()) {
EntityManager em = createEntityManager();
beginTransaction(em);
Assassin assassin = null;
try {
assassin = new Assassin();
assassin.setName("OptLockAssassin");
em.persist(assassin);
commitTransaction(em);
} catch (RuntimeException ex) {
if (isTransactionActive(em)) {
rollbackTransaction(em);
}
closeEntityManager(em);
throw ex;
}
EntityManager em2 = createEntityManager();
Exception optimisticLockException = null;
beginTransaction(em);
try {
assassin = em.find(Assassin.class, assassin.getId());
em.lock(assassin, LockModeType.WRITE);
beginTransaction(em2);
try {
Assassin assassin2 = em2.find(Assassin.class, assassin.getId());
assassin2.setName("OptLockAssassin2");
commitTransaction(em2);
em2.close();
} catch (RuntimeException ex) {
if (isTransactionActive(em2)) {
rollbackTransaction(em2);
}
closeEntityManager(em2);
throw ex;
}
try {
em.flush();
} catch (PersistenceException exception) {
if (exception instanceof OptimisticLockException){
optimisticLockException = exception;
} else {
throw exception;
}
}
rollbackTransaction(em);
} catch (RuntimeException ex) {
if (isTransactionActive(em)){
rollbackTransaction(em);
}
closeEntityManager(em);
throw ex;
}
try {
beginTransaction(em);
assassin = em.find(Assassin.class, assassin.getId());
em.remove(assassin);
commitTransaction(em);
} catch (RuntimeException ex) {
if (isTransactionActive(em)) {
rollbackTransaction(em);
}
closeEntityManager(em);
throw ex;
}
assertFalse("Proper exception not thrown when EntityManager.lock(object, OPTIMISTIC) is used.", optimisticLockException == null);
}
}
// Gun uses an ALL_COLUMNS optimistic locking policy.
public void testGunOptimisticLocking() {
// Cannot create parallel entity managers in the server.
if (! isOnServer()) {
EntityManager em1 = createEntityManager();
EntityManager em2 = createEntityManager();
em1.getTransaction().begin();
em2.getTransaction().begin();
RuntimeException caughtException = null;
try {
Gun gun1 = em1.find(Gun.class, gunSerialNumber);
Gun gun2 = em2.find(Gun.class, gunSerialNumber);
gun1.setCaliber(12);
gun2.setCaliber(22);
em1.getTransaction().commit();
em2.getTransaction().commit();
em1.close();
em2.close();
} catch (RuntimeException e) {
if (em1.getTransaction().isActive()){
em1.getTransaction().rollback();
}
if (em2.getTransaction().isActive()){
em2.getTransaction().rollback();
}
if (e.getCause() instanceof jakarta.persistence.OptimisticLockException) {
caughtException = e;
} else {
throw e;
}
} finally {
em1.close();
em2.close();
}
if (caughtException == null) {
fail("Optimistic lock exception was not thrown.");
}
}
}
// Note: Update all for Table Per class only works with the one single
// reference class. So it's not a full feature test.
public void testUpdateAllQuery() {
EntityManager em = createEntityManager();
beginTransaction(em);
try {
ExpressionBuilder eb = new ExpressionBuilder();
UpdateAllQuery updateQuery = new UpdateAllQuery(Assassin.class);
updateQuery.addUpdate(eb.get("name"), "Generic Assassin Name");
((JpaEntityManager)em.getDelegate()).getServerSession().executeQuery(updateQuery);
Assassin assassin = (Assassin) em.find(ContractedPersonel.class, assassinId);
em.refresh(assassin);
commitTransaction(em);
assertTrue("Update all did not work", assassin.getName().equals("Generic Assassin Name"));
} catch (Exception e) {
e.printStackTrace();
fail("Error issuing update all contracted personel query: " + e.getMessage());
} finally {
if (isTransactionActive(em)){
rollbackTransaction(em);
}
closeEntityManager(em);
}
}
/**
* Commenting out this test. It didn't not work and well I'll leave it here
* for now in case we pick this up again some other time.
*/
/*
public void testBatchQueryHint(){
int id1 = 0;
EntityManager em = createEntityManager();
beginTransaction(em);
Assassin assassin1 = new Assassin();
assassin1.setName("Assassin1");
Weapon weapon = new Weapon();
weapon.setDescription("A generic weapon");
weapon.setAssassin(assassin1);
assassin1.setWeapon(weapon);
em.persist(assassin1);
//id1 = manager.getId();
Assassin assassin2 = new Assassin();
assassin2.setName("Assassin2");
Poison poison = new Poison();
poison.setDescription("A slow death poison");
poison.setEffectTime(Poison.EFFECTTIME.PROLONGED);
assassin2.setWeapon(poison);
em.persist(assassin2);
commitTransaction(em);
em.clear();
JpaQuery query = (JpaQuery) getEntityManagerFactory().createEntityManager().createQuery("SELECT a FROM Assassin a WHERE a.id > 0 order by a.name");
query.setHint(QueryHints.BATCH, "a.weapon");
query.setHint(QueryHints.BATCH, "a.eliminations");
ReadAllQuery raq = (ReadAllQuery)query.getDatabaseQuery();
List expressions = raq.getBatchReadAttributeExpressions();
assertTrue(expressions.size() == 2);
Expression exp = (Expression)expressions.get(0);
assertTrue(exp.isQueryKeyExpression());
assertTrue("Query key name was not weapon", exp.getName().equals("weapon"));
exp = (Expression)expressions.get(1);
assertTrue(exp.isQueryKeyExpression());
assertTrue("Query key name was not eliminations", exp.getName().equals("eliminations"));
List resultList = query.getResultList();
Assassin assassin = (Assassin) resultList.get(0);
assassin.getWeapon().hashCode();
assassin = (Assassin) resultList.get(1);
assassin.getWeapon().hashCode();
}
*/
}