mirror of https://github.com/apache/openjpa.git
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:
parent
f7b6f944b2
commit
c27f31a107
|
@ -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 {
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
Loading…
Reference in New Issue