मुझे इसका कुछ हल मिल गया है।
मैप्ड एंटिटीज़ (JPA 2.0) का उपयोग करना
JPA 2.0 का उपयोग करके एक देशी क्वेरी को POJO में मैप करना संभव नहीं है, यह केवल एक इकाई के साथ किया जा सकता है।
उदाहरण के लिए:
Query query = em.createNativeQuery("SELECT name,age FROM jedi_table", Jedi.class);
@SuppressWarnings("unchecked")
List<Jedi> items = (List<Jedi>) query.getResultList();
लेकिन इस मामले में, Jedi
एक मैप्ड इकाई वर्ग होना चाहिए।
यहां अनियंत्रित चेतावनी से बचने का एक विकल्प, एक नामित देशी क्वेरी का उपयोग करना होगा। तो अगर हम एक इकाई में देशी क्वेरी की घोषणा करते हैं
@NamedNativeQuery(
name="jedisQry",
query = "SELECT name,age FROM jedis_table",
resultClass = Jedi.class)
फिर, हम बस कर सकते हैं:
TypedQuery<Jedi> query = em.createNamedQuery("jedisQry", Jedi.class);
List<Jedi> items = query.getResultList();
यह सुरक्षित है, लेकिन हम अभी भी मैप की गई इकाई का उपयोग करने के लिए प्रतिबंधित हैं।
मैनुअल मैपिंग
एक समाधान जो मैंने थोड़ा प्रयोग किया (जेपीए 2.1 के आने से पहले) एक पीओजेओ कंस्ट्रक्टर के खिलाफ थोड़ा प्रतिबिंब का उपयोग करके मैपिंग कर रहा था।
public static <T> T map(Class<T> type, Object[] tuple){
List<Class<?>> tupleTypes = new ArrayList<>();
for(Object field : tuple){
tupleTypes.add(field.getClass());
}
try {
Constructor<T> ctor = type.getConstructor(tupleTypes.toArray(new Class<?>[tuple.length]));
return ctor.newInstance(tuple);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
यह विधि मूल रूप से टुपल ऐरे (मूल प्रश्नों द्वारा लौटाए गए) के रूप में लेती है और एक प्रदान किए गए POJO वर्ग के खिलाफ एक ऐसे निर्माता की तलाश करती है, जिसमें समान फ़ील्ड्स और समान प्रकार की संख्या हो।
तब हम सुविधाजनक तरीकों का उपयोग कर सकते हैं:
public static <T> List<T> map(Class<T> type, List<Object[]> records){
List<T> result = new LinkedList<>();
for(Object[] record : records){
result.add(map(type, record));
}
return result;
}
public static <T> List<T> getResultList(Query query, Class<T> type){
@SuppressWarnings("unchecked")
List<Object[]> records = query.getResultList();
return map(type, records);
}
और हम बस इस तकनीक का उपयोग इस प्रकार कर सकते हैं:
Query query = em.createNativeQuery("SELECT name,age FROM jedis_table");
List<Jedi> jedis = getResultList(query, Jedi.class);
JPA 2.1 @SqlResultSetMapping के साथ
JPA 2.1 के आगमन के साथ, हम समस्या को हल करने के लिए @SqlResultSetMapping एनोटेशन का उपयोग कर सकते हैं।
हमें किसी इकाई में कहीं भी परिणाम सेट मैपिंग घोषित करने की आवश्यकता है:
@SqlResultSetMapping(name="JediResult", classes = {
@ConstructorResult(targetClass = Jedi.class,
columns = {@ColumnResult(name="name"), @ColumnResult(name="age")})
})
और फिर हम बस करते हैं:
Query query = em.createNativeQuery("SELECT name,age FROM jedis_table", "JediResult");
@SuppressWarnings("unchecked")
List<Jedi> samples = query.getResultList();
बेशक, इस मामले में Jedi
एक मैपेड इकाई होने की आवश्यकता नहीं है। यह एक नियमित पीओजेओ हो सकता है।
XML मैपिंग का उपयोग करना
मैं उन लोगों में से एक @SqlResultSetMapping
हूं जो अपनी संस्थाओं में इन सभी सुंदर आक्रामक को जोड़ते हैं , और मैं विशेष रूप से संस्थाओं के भीतर नामित प्रश्नों की परिभाषा को नापसंद करता हूं, इसलिए वैकल्पिक रूप से मैं यह सब META-INF/orm.xml
फाइल में करता हूं :
<named-native-query name="GetAllJedi" result-set-mapping="JediMapping">
<query>SELECT name,age FROM jedi_table</query>
</named-native-query>
<sql-result-set-mapping name="JediMapping">
<constructor-result target-class="org.answer.model.Jedi">
<column name="name" class="java.lang.String"/>
<column name="age" class="java.lang.Integer"/>
</constructor-result>
</sql-result-set-mapping>
और वे सभी उपाय मुझे पता हैं। अंतिम दो आदर्श तरीके हैं यदि हम जेपीए 2.1 का उपयोग कर सकते हैं।