OPENJPA-899: Initial support for new JPA 2.0 Query.getHints() API method.

git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@740911 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Pinaki Poddar 2009-02-04 22:06:47 +00:00
parent f7b6f944b2
commit c27f31a107
6 changed files with 169 additions and 146 deletions

View File

@ -19,6 +19,7 @@
package org.apache.openjpa.kernel; package org.apache.openjpa.kernel;
import java.util.Collection; import java.util.Collection;
import java.util.Map;
import java.util.Set; import java.util.Set;
import org.apache.openjpa.lib.rop.ResultList; import org.apache.openjpa.lib.rop.ResultList;
@ -436,8 +437,16 @@ public class DelegatingFetchConfiguration
return _fetch.getHint(name); return _fetch.getHint(name);
} catch (RuntimeException re) { } catch (RuntimeException re) {
throw translate(re); throw translate(re);
} }
} }
public Map<String, Object> getHints() {
try {
return _fetch.getHints();
} catch (RuntimeException re) {
throw translate(re);
}
}
public int requiresFetch(FieldMetaData fmd) { public int requiresFetch(FieldMetaData fmd) {
try { try {

View File

@ -20,6 +20,7 @@ package org.apache.openjpa.kernel;
import java.io.Serializable; import java.io.Serializable;
import java.util.Collection; import java.util.Collection;
import java.util.Map;
import java.util.Set; import java.util.Set;
import org.apache.openjpa.lib.rop.ResultList; import org.apache.openjpa.lib.rop.ResultList;
@ -305,6 +306,13 @@ public interface FetchConfiguration
* @since 0.4.0 * @since 0.4.0
*/ */
public Object getHint (String name); public Object getHint (String name);
/**
* Returns an immutable view of the currently active hints and their values.
*
* @since 2.0.0
*/
public Map<String, Object> getHints();
/** /**
* Root classes for recursive operations. This set is not thread safe. * Root classes for recursive operations. This set is not thread safe.

View File

@ -29,6 +29,7 @@ import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.TreeMap;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.conf.OpenJPAConfiguration;
@ -463,6 +464,16 @@ public class FetchConfigurationImpl
public Object getHint(String name) { public Object getHint(String name) {
return (_state.hints == null) ? null : _state.hints.get(name); return (_state.hints == null) ? null : _state.hints.get(name);
} }
public Map<String, Object> getHints() {
if (_state.hints == null)
return (Map<String, Object>)Collections.EMPTY_MAP;
Map<String, Object> result = new TreeMap<String, Object>();
for (Object key : _state.hints.keySet()) {
result.put(key.toString(), _state.hints.get(key));
}
return result;
}
public Set getRootClasses() { public Set getRootClasses() {
return (_state.rootClasses == null) ? Collections.EMPTY_SET return (_state.rootClasses == null) ? Collections.EMPTY_SET

View File

@ -28,7 +28,9 @@ import javax.persistence.EntityResult;
import javax.persistence.Id; import javax.persistence.Id;
import javax.persistence.Inheritance; import javax.persistence.Inheritance;
import javax.persistence.InheritanceType; import javax.persistence.InheritanceType;
import javax.persistence.NamedNativeQuery;
import javax.persistence.OneToOne; import javax.persistence.OneToOne;
import javax.persistence.QueryHint;
import javax.persistence.SqlResultSetMapping; import javax.persistence.SqlResultSetMapping;
import javax.persistence.Table; import javax.persistence.Table;
import javax.persistence.Version; import javax.persistence.Version;
@ -37,7 +39,10 @@ import javax.persistence.Version;
@Entity @Entity
@Table(name="entity_1") @Table(name="entity_1")
@Inheritance(strategy=InheritanceType.JOINED) @Inheritance(strategy=InheritanceType.JOINED)
@SqlResultSetMapping(name="NativeTestResult", entities=@EntityResult(entityClass=Entity1.class)) @SqlResultSetMapping(name="NativeTestResult",
entities=@EntityResult(entityClass=Entity1.class))
@NamedNativeQuery(name="SQLWithHints", query="SELECT * FROM ENTITY_1",
hints={@QueryHint(name="XYZ", value="abc")})
public class Entity1 implements Serializable public class Entity1 implements Serializable
{ {
private static final long serialVersionUID = 2882935803066041165L; private static final long serialVersionUID = 2882935803066041165L;

View File

@ -18,153 +18,139 @@
*/ */
package org.apache.openjpa.persistence.jdbc.mapping; package org.apache.openjpa.persistence.jdbc.mapping;
import java.util.List;
import javax.persistence.*; import javax.persistence.EntityManager;
import java.util.*; import javax.persistence.Query;
import org.apache.openjpa.persistence.jdbc.common.apps.mappingApp.*; import org.apache.openjpa.kernel.QueryLanguages;
import org.apache.openjpa.persistence.common.utils.*; import org.apache.openjpa.persistence.OpenJPAPersistence;
import junit.framework.*; import org.apache.openjpa.persistence.jdbc.common.apps.mappingApp.Entity1;
import org.apache.openjpa.persistence.jdbc.common.apps.mappingApp.Entity2;
import org.apache.openjpa.persistence.test.SingleEMFTestCase;
public class TestNativeQueries extends SingleEMFTestCase {
private static final String TABLE_NAME = "entity_1";
private static final String CONST_NAME = "testSimple";
private static final int CONST_INT = 42;
private EntityManager em;
public void setUp() {
super.setUp(CLEAR_TABLES, Entity1.class, Entity2.class);
public class TestNativeQueries extends AbstractTestCase em = emf.createEntityManager();
{ em.getTransaction().begin();
em.persist(new Entity1(1, CONST_NAME, CONST_INT));
public TestNativeQueries(String name) em.persist(new Entity1(2, CONST_NAME+" Changed", CONST_INT+1));
{ em.persist(new Entity1(3, CONST_NAME+" Changed 2", CONST_INT+2));
super(name, "jdbccactusapp"); em.getTransaction().commit();
} em.getTransaction().begin();
}
public void setUp () public void testNoParameter() {
{ String sql = "SELECT * FROM " + TABLE_NAME;
deleteAll (Entity1.class); assertSize(3, em.createNativeQuery(sql, Entity1.class).getResultList());
} }
public void testLiteral() {
String sql = "SELECT * FROM " + TABLE_NAME
+ " WHERE INTFIELD = " + CONST_INT;
assertSize(1, em.createNativeQuery(sql, Entity1.class).getResultList());
}
public void testParameter() {
String sql = "SELECT * FROM " + TABLE_NAME
+ " WHERE INTFIELD = ?1";
assertSize(1, em.createNativeQuery(sql, Entity1.class)
.setParameter(1, CONST_INT)
.getResultList());
}
public void testOutOfOrderParameter() {
String sql = "SELECT * FROM " + TABLE_NAME
+ " WHERE INTFIELD = ?2 AND STRINGFIELD = ?1";
assertSize(1, em.createNativeQuery(sql, Entity1.class)
.setParameter(2, CONST_INT)
.setParameter(1, CONST_NAME)
.getResultList());
}
public void testDuplicateParameter() {
String sql = "SELECT * FROM " + TABLE_NAME
+ " WHERE INTFIELD = ?1 AND INTFIELD = ?1";
assertSize(1, em.createNativeQuery(sql, Entity1.class)
.setParameter(1, CONST_INT)
.getResultList());
}
public void testDifferentParameterToSameField() {
String sql = "SELECT * FROM " + TABLE_NAME
+ " WHERE INTFIELD = ?1 OR INTFIELD = ?2";
assertSize(2, em.createNativeQuery(sql, Entity1.class)
.setParameter(1, CONST_INT)
.setParameter(2, CONST_INT+1)
.getResultList());
}
public void testSimple () public void testQuoteParameterIgnored() {
{ String sql = "SELECT * FROM " + TABLE_NAME
deleteAll (Entity1.class); + " WHERE INTFIELD = ?1 OR STRINGFIELD = '?2'";
assertSize(1, em.createNativeQuery(sql, Entity1.class)
.setParameter(1, CONST_INT)
.getResultList());
}
public void testParameterMarkerWithoutSpaces() {
String sql = "SELECT * FROM " + TABLE_NAME
+ " WHERE INTFIELD=?1";
assertSize(1, em.createNativeQuery(sql, Entity1.class)
.setParameter(1, CONST_INT)
.getResultList());
}
public void testZeroBasedParameterSettingFails() {
try {
String sql = "SELECT * FROM " + TABLE_NAME
+ " WHERE INTFIELD = ?1";
em.createNativeQuery(sql, Entity1.class)
.setParameter(0, 12);
fail("Expected to fail with 0 parameter index");
} catch (Exception e) {
// as expected
}
}
// test create public void testNamedParameterFails() {
{ /*
EntityManager em = currentEntityManager( ); * Named parameters are not supported according to Section 3.6.8 of
startTx(em); * JPA 2.0 (pp 100) public draft Oct 31, 2008:
em.persist (new Entity1 (0, "testSimple", 12)); * "The use of named parameters is not defined for native queries.
endTx(em); * Only positional parameter binding for SQL queries may be used by
endEm(em); * portable applications."
} */
String sql = "SELECT * FROM " + TABLE_NAME + " WHERE INTFIELD = :p";
try {
em.createNativeQuery (sql, Entity1.class)
.setParameter ("p", 12);
fail("Expected to fail with NAMED parameter");
} catch (IllegalArgumentException ex) {
// good
}
}
public void testHintsAreProcessed() {
Query q = em.createNamedQuery("SQLWithHints");
assertEquals(QueryLanguages.LANG_SQL,
OpenJPAPersistence.cast(q).getLanguage());
String hintKey = "XYZ";
assertTrue(q.getHints().containsKey(hintKey));
assertEquals("abc", q.getHints().get(hintKey));
}
// test Query public void assertSize(int num, List l) {
{ assertNotNull(l);
/* JDBCConfiguration conf = (JDBCConfiguration)getConfiguration (); assertEquals(num, l.size());
DBDictionary dict = conf.getDBDictionaryInstance ();*/ }
/* String tableName = dict.getFullName (conf.getMappingRepository ().
getMapping (Entity1.class, getClass ().getClassLoader (), true).
getTable (), false);*/
EntityManager em = currentEntityManager( );
startTx(em);
String tableName = "entity_1";
assertSize (1, em.createNativeQuery
("SELECT * FROM " + tableName, Entity1.class).
getResultList ());
assertSize (1, em.createNativeQuery ("SELECT * FROM " + tableName
+ " WHERE INTFIELD = 12", Entity1.class).
getResultList ());
assertSize (1, em.createNativeQuery ("SELECT * FROM " + tableName
+ " WHERE INTFIELD = ?1", Entity1.class).
setParameter (1, 12).
getResultList ());
// make sure that out-of-order parameters work
assertSize (1, em.createNativeQuery ("SELECT * FROM " + tableName
+ " WHERE INTFIELD = ?2 AND STRINGFIELD = ?1", Entity1.class).
setParameter (2, 12).
setParameter (1, "testSimple").
getResultList ());
// make sure duplicate parameters work
assertSize (1, em.createNativeQuery ("SELECT * FROM " + tableName
+ " WHERE INTFIELD = ?1 AND INTFIELD = ?1", Entity1.class).
setParameter (1, 12).
getResultList ());
assertSize (1, em.createNativeQuery ("SELECT * FROM " + tableName
+ " WHERE INTFIELD = ?1 OR INTFIELD = ?2", Entity1.class).
setParameter (1, 12).
setParameter (2, 13).
getResultList ());
// make sure that quoted parameters are ignored as expected
assertSize (1, em.createNativeQuery ("SELECT * FROM " + tableName
+ " WHERE INTFIELD = ?1 OR STRINGFIELD = '?5'", Entity1.class).
setParameter (1, 12).
getResultList ());
// test without spaces
assertSize (1, em.createNativeQuery ("SELECT * FROM " + tableName
+ " WHERE INTFIELD=?1 OR STRINGFIELD='?5'", Entity1.class).
setParameter (1, 12).
getResultList ());
/* assertSize (1, ((QueryImpl)em.createNativeQuery
("SELECT * FROM " + tableName
+ " WHERE INTFIELD = ?1 OR INTFIELD = ?2", Entity1.class)).
setParameters (12, 1).
getResultList ());
assertSize (0, ((QueryImpl)em.createNativeQuery
("SELECT * FROM " + tableName
+ " WHERE INTFIELD = ?1 AND INTFIELD = ?2", Entity1.class)).
setParameters (12, 1).
getResultList ());
*/
assertSize (0, em.createNativeQuery ("SELECT * FROM " + tableName
+ " WHERE INTFIELD = ?1 AND INTFIELD = ?2", Entity1.class).
setParameter (1, 12).
setParameter (2, 13).
getResultList ());
try
{
em.createNativeQuery ("SELECT * FROM " + tableName
+ " WHERE INTFIELD = ?1", Entity1.class).
setParameter (0, 12).
getResultList ();
fail ("Should not have been able to use param index 0");
}
catch (Exception e)
{
// as expected
}
/*
* Named parameters are not supported according to 19 June 3.5.2:
*
* The use of named parameters is not defined for
* native queries. Only positional parameter binding
* for SQL queries may be used by portable applications.
*
assertSize (1, em.createNativeQuery ("SELECT * FROM " + tableName
+ " WHERE INTFIELD = :p", Entity1.class).
setParameter ("p", 12).
getResultList ());
assertSize (1, em.createNativeQuery ("SELECT * FROM " + tableName
+ " WHERE INTFIELD = :p OR INTFIELD = :p", Entity1.class).
setParameter ("p", 12).
getResultList ());
*/
endTx(em);
endEm(em);
}
}
public boolean assertSize(int num, List l)
{
return(num == l.size());
}
} }

View File

@ -601,9 +601,13 @@ public class QueryImpl implements OpenJPAQuerySPI, Serializable {
return _query.equals(((QueryImpl) other)._query); return _query.equals(((QueryImpl) other)._query);
} }
/**
* Get all the active hints and their values.
*
*/
//TODO: JPA 2.0 Hints that are not set to FetchConfiguration
public Map<String, Object> getHints() { public Map<String, Object> getHints() {
throw new UnsupportedOperationException( return _query.getFetchConfiguration().getHints();
"JPA 2.0 - Method not yet implemented");
} }
public LockModeType getLockMode() { public LockModeType getLockMode() {