আমি এর বেশ কয়েকটি সমাধান খুঁজে পেয়েছি।
ম্যাপযুক্ত সত্তা (JPA 2.0) ব্যবহার করা হচ্ছে
জেপিএ ২.০ ব্যবহার করে কোনও পোজোর নেটিভ কোয়েরি মানচিত্র করা সম্ভব নয়, এটি কেবল কোনও সত্তা দিয়েই করা যেতে পারে।
এই ক্ষেত্রে:
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();
এটি নিরাপদ, তবে আমরা এখনও ম্যাপযুক্ত সত্তা ব্যবহারের জন্য সীমাবদ্ধ।
ম্যানুয়াল ম্যাপিং
একটি সমাধান যা আমি কিছুটা পরীক্ষিত করেছিলাম (জেপিএ ২.১ এর আগমনের আগে) কিছুটা প্রতিবিম্ব ব্যবহার করে কোনও POJO নির্মাণকারীর বিরুদ্ধে ম্যাপিং করছিল।
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);
@ স্কেলআরসাল্টসেটম্যাপিং সহ জেপিএ ২.১
জেপিএ ২.১ এর আগমনের সাথে সাথে আমরা সমস্যার সমাধান করতে @ এসকিএলআরসাল্টস্যাপম্যাপিং টিকাটি ব্যবহার করতে পারি।
আমাদের কোনও সত্তার কোথাও একটি ফলাফল সেট ম্যাপিং ঘোষণা করতে হবে:
@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
কোনও ম্যাপযুক্ত সত্তা হওয়ার দরকার নেই। এটি নিয়মিত POJO হতে পারে।
এক্সএমএল ম্যাপিং ব্যবহার করে
আমি তাদের মধ্যে যারা @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>
এবং এগুলি আমার জানা সমস্ত সমাধান। শেষ দুটি হল আদর্শ উপায় যদি আমরা জেপিএ ২.১ ব্যবহার করতে পারি।