জেপিএ: কীভাবে কোনও দেশীয় ক্যোয়ারী ফলাফলকে পোজো শ্রেণি সংগ্রহে সেট করা যায়


174

আমি আমার প্রকল্পে জেপিএ ব্যবহার করছি।

আমি একটি ক্যোয়ারিতে এসেছি যাতে পাঁচটি টেবিলগুলিতে আমার যোগদানের কাজটি করা দরকার। সুতরাং আমি একটি নেটিভ ক্যোয়ারী তৈরি করেছি যা পাঁচটি ক্ষেত্র ফেরত দেয়।

এখন আমি ফলাফল অবজেক্টটিকে জাভা পোজো ক্লাসে রূপান্তর করতে চাই যাতে একই পাঁচটি স্ট্রিং রয়েছে।

জেপিএ-তে কোনও উপায় আছে যে ফলটি সরাসরি পজো অবজেক্ট তালিকায় ফেলে দেবে ??

আমি নিম্নলিখিত সমাধানে এসেছি ..

@NamedNativeQueries({  
    @NamedNativeQuery(  
        name = "nativeSQL",  
        query = "SELECT * FROM Actors",  
        resultClass = db.Actor.class),  
    @NamedNativeQuery(  
        name = "nativeSQL2",  
        query = "SELECT COUNT(*) FROM Actors",  
        resultClass = XXXXX) // <--------------- problem  
})  

এখন এখানে রেজাল্ট ক্লাসে, আমাদের কি এমন শ্রেণি সরবরাহ করা দরকার যা প্রকৃত জেপিএ সত্তা? অথবা আমরা এটিকে যে কোনও জাভা পোজো ক্লাসে রূপান্তর করতে পারি যাতে একই কলামের নাম রয়েছে?


এই উত্তরটি পরীক্ষা করুন। এটির সম্পূর্ণ উত্তর রয়েছে: stackoverflow.com/a/50365522/3073945
মোঃ সাজেদুল করিম

সে বসন্ত নয়, জেপিএ ব্যবহার করছে
তাকে

উত্তর:


103

জেপিএ এমন একটি সরবরাহ করে SqlResultSetMappingযা আপনাকে আপনার স্থানীয় ক্যোয়ারী থেকে কোনও সত্তায় ফিরে আসার মানচিত্র তৈরি করতে দেয়বা একটি কাস্টম ক্লাস

সম্পাদনা করুন জেপিএ 1.0 অ-সত্তা ক্লাসগুলিতে ম্যাপিংয়ের অনুমতি দেয় না। কেবল জেপিএ ২.১-এ একটি কন্সট্রাক্টর রিসাল্ট মানচিত্রের জাভা শ্রেণীর মানচিত্রে যুক্ত করা হয়েছে।

এছাড়াও, গণনা পাওয়ার সাথে ওপির সমস্যার জন্য একটি একক দিয়ে ফলাফল সেট ম্যাপিং সংজ্ঞায়িত করার জন্য এটি যথেষ্ট হওয়া উচিত ColumnResult


1
উত্তরের জন্য ধন্যবাদ. এখানে আমরা "@EntityResult" এবং "@FeldResult" টীকা সহ থা জাভা সত্তা শ্রেণীর সাথে সত্তার সাথে আমাদের ফলাফলটি ম্যাপ করছি। সেটা ঠিক আছে. তবে এখানে আমার আরও স্পষ্টতা দরকার। আমরা যে ক্লাসটির ফলাফলের সাথে ম্যাপিং করছি তা অবশ্যই জেপিএ সত্তা শ্রেণি হতে হবে? অথবা আমরা একটি সরল POJO ক্লাস ব্যবহার করতে পারি যা কোনও সত্তা ক্রয় নয় যা ফলাফল সেটে কলামগুলির মতো প্রয়োজনীয় সমস্ত চলক রয়েছে।
গুঞ্জন শাহ

1
@ গুঞ্জনশাহ: জানার সর্বোত্তম উপায় হ'ল চেষ্টা করে দেখুন :) এছাড়াও, কোনও সত্তা হ'ল একই পোজো, কিছু টিকা আছে। যতক্ষণ আপনি এটি চালিয়ে যাওয়ার চেষ্টা করছেন না, ততক্ষণ এটি পোজো থাকবে।
ডেনিস তুলসকি

2
আমি এটি চেষ্টা করার সময় আমি একটি ত্রুটি পেয়েছি যে ক্লাসটি একটি পরিচিত সত্তা নয়। নেটিভ ক্যোয়ারী ব্যবহার করার চেষ্টা করার পরিবর্তে আমি এই পদ্ধতির stackoverflow.com/questions/5024533/… ব্যবহার করে শেষ করেছি ।
এফগ্রিগ

2
@ এডউইনডালোরজো: এটি জেপিএ 1.0 এর জন্য সঠিক। জেপিএ ২.১ এ তারা ConstructorResultপ্যারামিটারগুলির একটি হিসাবে যুক্ত করেছে SqlResultSetMappingযা কনস্ট্রাক্টরে সেট সমস্ত ক্ষেত্রের সাথে একটি পোজো ব্যবহার করতে দেয়। আমি উত্তর আপডেট করব।
ডেনিস তুলসকি

4
আমি আরেকটি তিক্ত সত্য দেখতে পাচ্ছি: কনস্ট্রাক্টর রেজাল্ট কোনও পোজোতে মানচিত্র বানাতে পারে .. তবে কনস্ট্রাক্টরআরসাল্ট নিজেই সত্তা শ্রেণিতে থাকতে হবে যাতে আপনি এড়াতে পারবেন না ... এবং সেইজন্য আরও বড় কঠিন সত্য: আপনার যত্নের সাথে কিছু ফলাফলের প্রয়োজন নেই প্রাথমিক-কী-তে এখনও আপনার সত্তায় @ আইডি থাকতে হবে ... হাস্যকর অধিকার?
অর্ণব দত্ত

210

আমি এর বেশ কয়েকটি সমাধান খুঁজে পেয়েছি।

ম্যাপযুক্ত সত্তা (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>

এবং এগুলি আমার জানা সমস্ত সমাধান। শেষ দুটি হল আদর্শ উপায় যদি আমরা জেপিএ ২.১ ব্যবহার করতে পারি।


1
সিডিনোট: আমি সবেমাত্র JPA2.1 নির্ভরতার সাথে JPA 2.0 পদ্ধতির ব্যবহার করেছি এবং এটি ব্যর্থ হয়েছে। সুতরাং সম্ভবত এটি নীচের দিকে সামঞ্জস্যপূর্ণ নয় ...
সদস্যরা

1
"সত্তার কোথাও" বলতে কী বোঝ? আমার পোজো কোনও জেপিএ সত্তা নয় আমি কি আমার পোজোতে @SllResultSetMapping ঘোষণা করতে পারি না? আমি জেপিএ ২.১ সমাধানগুলিতে আগ্রহী। দয়া করে কিছুটা সুনির্দিষ্ট হন।
আলবোজ

3
@ আলবোজকে @SqlResultSetMappingঅবশ্যই একটি সত্তায় স্থাপন করতে হবে কারণ এটিই জেপিএ মেটাডেটা পড়তে চলেছে। আপনি জেপিএ আপনার পিজোগুলি পরিদর্শন করবেন বলে আশা করতে পারবেন না। আপনি যে সত্তাটিতে ম্যাপিংটি স্থাপন করেছেন সেটি অপ্রাসঙ্গিক, সম্ভবত এটিই আপনার পোজোর ফলাফলের সাথে সম্পর্কিত। বিকল্পভাবে ম্যাপিংটি এক্সএমএলে প্রকাশ করা যেতে পারে সম্পূর্ণরূপে সম্পর্কিত নয় এমন সত্তার সাথে মিলিত হওয়া এড়াতে।
এডউইন ডালোরজো

1
কন্সট্রাক্টরসাল্টের পক্ষে নীস্ট ক্লাস থাকা কোনও ক্লাস ব্যবহার করা কি সম্ভব?
ক্রিসমার্ক

5
যদি @SqlResultSetMappingএটির সাথে জেপিএ ২.১ ব্যবহার করা যায় তবে এটি লক্ষণীয় যে Jediশ্রেণীর জন্য একটি সর্ব-আরগ নির্মাতার প্রয়োজন হবে এবং @ColumnResultটীকাটি typeরূপান্তরগুলিতে যুক্ত বৈশিষ্ট্যটির প্রয়োজন হতে পারে যা অন্তর্নিহিত নাও হতে পারে ( type = ZonedDateTime.classকিছু কলামের জন্য আমার যোগ করার দরকার ছিল )।
গ্লেন

11

হ্যাঁ, জেপিএ ২.১ সহ এটি সহজ। আপনার কাছে খুব দরকারী টিকা রয়েছে। তারা আপনার জীবন সরল করে।

প্রথমে আপনার নেটিভ ক্যোয়ারী ঘোষণা করুন, তারপরে আপনার ফলাফল সেট ম্যাপিং (যা আপনার পিওজেও ডেটাবেস দ্বারা ফিরিয়ে দেওয়া ডেটা ম্যাপিং সংজ্ঞা দেয়)। উল্লেখ করার জন্য আপনার POJO ক্লাসটি লিখুন (বংশবৃদ্ধির জন্য এখানে অন্তর্ভুক্ত নেই)। সর্বশেষে তবে সর্বনিম্ন নয়: ডিএওতে একটি পদ্ধতি তৈরি করুন (উদাহরণস্বরূপ) কোয়েরিকে কল করার জন্য। এটি আমার জন্য একটি ড্রপউইজার্ড (1.0.0) অ্যাপে কাজ করেছে।

প্রথমে কোনও সত্তা শ্রেণিতে নেটিভ ক্যোয়ারী ঘোষণা করুন:

@NamedNativeQuery (
name = "domain.io.MyClass.myQuery",
query = "Select a.colA, a.colB from Table a",
resultSetMapping = "mappinMyNativeQuery")   // must be the same name as in the SqlResultSetMapping declaration

নীচে আপনি ফলাফল ম্যাপিং ঘোষণাটি যুক্ত করতে পারেন:

@SqlResultSetMapping(
name = "mapppinNativeQuery",  // same as resultSetMapping above in NativeQuery
   classes = {
      @ConstructorResult( 
          targetClass = domain.io.MyMapping.class,
          columns = {
               @ColumnResult( name = "colA", type = Long.class),  
               @ColumnResult( name = "colB", type = String.class)
          }
      )
   } 
)

পরে ডিএওতে আপনি কোয়েরিটি হিসাবে উল্লেখ করতে পারেন

public List<domain.io.MyMapping> findAll() {
        return (namedQuery("domain.io.MyClass.myQuery").list());
    }

এটাই.


উত্তম উত্তর, তবে আমি মনে করি আপনি প্রথম @ কলামআরসাল্ট টীকাটি পরে কোনও প্রথম বন্ধনী মিস করেছেন।
এমওয়াত্জার

কোডটিতে ভুল রয়েছে তবে সংশোধন করা সহজ। উদাহরণস্বরূপ: "রেজুলসেটম্যাপিং =" হওয়া উচিত "রেজাল্টসেটম্যাপিং ="
জেডবাইজেক

3
আমি আরেকটি তিক্ত সত্য দেখতে পাচ্ছি: নামযুক্ত নেটিভ্যু কিউরি এবং স্কেলআরসাল্টসেটম্যাপিংটি একটি @Entity ক্লাসে থাকতে হবে
অর্ণব দত্ত

10

আপনি যদি ব্যবহার Spring-jpaকরেন তবে এটি উত্তর এবং এই প্রশ্নের পরিপূরক। কোন ত্রুটি থাকলে এটি সংশোধন করুন। আমি কোন Object[]ব্যবহারিক প্রয়োজনের ভিত্তিতে "পোজোর সাথে ম্যাপিং ফলাফল" অর্জন করতে প্রধানত তিনটি পদ্ধতি ব্যবহার করেছি:

  1. পদ্ধতিতে তৈরি জেপিএই যথেষ্ট।
  2. পদ্ধতিতে নির্মিত জেপিএ যথেষ্ট নয়, তবে এর sqlসাথে স্বনির্ধারিত Entityযথেষ্ট।
  3. প্রাক্তন 2 ব্যর্থ হয়েছে, এবং আমাকে একটি ব্যবহার করতে হবে nativeQuery। উদাহরণস্বরূপ এখানে। পোজো প্রত্যাশিত:

    public class Antistealingdto {
    
        private String secretKey;
    
        private Integer successRate;
    
        // GETTERs AND SETTERs
    
        public Antistealingdto(String secretKey, Integer successRate) {
            this.secretKey = secretKey;
            this.successRate = successRate;
        }
    }

পদ্ধতি 1 : পোজো একটি ইন্টারফেসে পরিবর্তন করুন:

public interface Antistealingdto {
    String getSecretKey();
    Integer getSuccessRate();
}

এবং সংগ্রহস্থল:

interface AntiStealingRepository extends CrudRepository<Antistealing, Long> {
    Antistealingdto findById(Long id);
}

পদ্ধতি 2 : সংগ্রহস্থল:

@Query("select new AntistealingDTO(secretKey, successRate) from Antistealing where ....")
Antistealing whatevernamehere(conditions);

দ্রষ্টব্য: POJO কনস্ট্রাক্টরের প্যারামিটার ক্রমটি POJO সংজ্ঞা এবং বর্গ উভয় ক্ষেত্রেই অভিন্ন হতে হবে।

পদ্ধতি 3 : ব্যবহার @SqlResultSetMappingএবং @NamedNativeQueryEntityএডুইন Dalorzo এর উত্তরে উদাহরণ হিসাবে।

প্রথম দুটি পদ্ধতি কাস্টমাইজড রূপান্তরকারীদের মতো অনেকগুলি মধ্য-মাঝারি হ্যান্ডলারকে কল করবে। উদাহরণস্বরূপ, AntiStealingএটিকে secretKeyস্থির রাখার আগে একটি সংজ্ঞা দেয় , এটি একটি এনক্রিপ্ট করার জন্য একটি রূপান্তরকারী প্রবেশ করানো হয়। এর ফলে প্রথম 2 টি পদ্ধতিতে রূপান্তরিত ফেরত ফিরে আসবে secretKeyযা আমি চাই না। 3 পদ্ধতিটি রূপান্তরকারীটিকে কাটিয়ে উঠবে এবং secretKeyএটি সঞ্চিত হিসাবে একই রকম হবে (একটি এনক্রিপ্ট করা)।


পদ্ধতি 1 টিতে আসলে বসন্তের প্রয়োজন হয় না এবং খাঁটি হাইবারনেট নিয়ে কাজ করে।
মার্টিন ভিসনি

@ মার্টিনভিজনি হ্যাঁ, এম 1 হ'ল জেপিকিউএল। কোনও প্রকল্প JPQL প্রয়োগ করে এটি সমর্থন করা উচিত। এইভাবে, সম্ভবত এম 2 এছাড়াও ব্যাপকভাবে সমর্থিত?
টাইনা

8

অ-সত্তা (যা মটরশুটি / পোজো) এর ফলাফল নির্ধারণের জন্য আন-র্যাপ প্রক্রিয়া সম্পাদন করা যেতে পারে। পদ্ধতিটি নিম্নরূপ:

List<JobDTO> dtoList = entityManager.createNativeQuery(sql)
        .setParameter("userId", userId)
        .unwrap(org.hibernate.Query.class).setResultTransformer(Transformers.aliasToBean(JobDTO.class)).list();

ব্যবহারটি জেপিএ-হাইবারনেট বাস্তবায়নের জন্য।


নোট করুন যে JobDTOডিফল্ট কনস্ট্রাক্টর থাকতে হবে। অথবা আপনি উপর ভিত্তি করে আপনার নিজের ট্রান্সফরমার বাস্তবায়ন হতে পারে AliasToBeanResultTransformerবাস্তবায়ন।
Lu55

4

প্রথমে নিম্নলিখিত মন্তব্যগুলি ঘোষণা করুন:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface NativeQueryResultEntity {
}

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface NativeQueryResultColumn {
    int index();
}

তারপরে নীচের মতো আপনার পজো এনেটেট করুন:

@NativeQueryResultEntity
public class ClassX {
    @NativeQueryResultColumn(index=0)
    private String a;

    @NativeQueryResultColumn(index=1)
    private String b;
}

তারপরে এনোটেশন প্রসেসরটি লিখুন:

public class NativeQueryResultsMapper {

    private static Logger log = LoggerFactory.getLogger(NativeQueryResultsMapper.class);

    public static <T> List<T> map(List<Object[]> objectArrayList, Class<T> genericType) {
        List<T> ret = new ArrayList<T>();
        List<Field> mappingFields = getNativeQueryResultColumnAnnotatedFields(genericType);
        try {
            for (Object[] objectArr : objectArrayList) {
                T t = genericType.newInstance();
                for (int i = 0; i < objectArr.length; i++) {
                    BeanUtils.setProperty(t, mappingFields.get(i).getName(), objectArr[i]);
                }
                ret.add(t);
            }
        } catch (InstantiationException ie) {
            log.debug("Cannot instantiate: ", ie);
            ret.clear();
        } catch (IllegalAccessException iae) {
            log.debug("Illegal access: ", iae);
            ret.clear();
        } catch (InvocationTargetException ite) {
            log.debug("Cannot invoke method: ", ite);
            ret.clear();
        }
        return ret;
    }

    // Get ordered list of fields
    private static <T> List<Field> getNativeQueryResultColumnAnnotatedFields(Class<T> genericType) {
        Field[] fields = genericType.getDeclaredFields();
        List<Field> orderedFields = Arrays.asList(new Field[fields.length]);
        for (int i = 0; i < fields.length; i++) {
            if (fields[i].isAnnotationPresent(NativeQueryResultColumn.class)) {
                NativeQueryResultColumn nqrc = fields[i].getAnnotation(NativeQueryResultColumn.class);
                orderedFields.set(nqrc.index(), fields[i]);
            }
        }
        return orderedFields;
    }
}

নিম্নরূপ উপরের কাঠামো ব্যবহার করুন:

String sql = "select a,b from x order by a";
Query q = entityManager.createNativeQuery(sql);

List<ClassX> results = NativeQueryResultsMapper.map(q.getResultList(), ClassX.class);

কোন প্যাকেজ মধ্যে BeanUtilsআছে?
হরিশ

4

সবচেয়ে সহজ উপায়টি তাই অনুমানগুলি ব্যবহার করা । এটি ক্যোয়ারির ফলাফলগুলিকে সরাসরি ইন্টারফেসে ম্যাপ করতে পারে এবং এসকিউএলআরসাল্টসেটম্যাপিং ব্যবহারের চেয়ে প্রয়োগ করা সহজ।

নীচে একটি উদাহরণ দেখানো হয়েছে:

@Repository
public interface PeopleRepository extends JpaRepository<People, Long> {

    @Query(value = "SELECT p.name AS name, COUNT(dp.people_id) AS count " +
        "FROM people p INNER JOIN dream_people dp " +
        "ON p.id = dp.people_id " +
        "WHERE p.user_id = :userId " +
        "GROUP BY dp.people_id " +
        "ORDER BY p.name", nativeQuery = true)
    List<PeopleDTO> findByPeopleAndCountByUserId(@Param("userId") Long userId);

    @Query(value = "SELECT p.name AS name, COUNT(dp.people_id) AS count " +
        "FROM people p INNER JOIN dream_people dp " +
        "ON p.id = dp.people_id " +
        "WHERE p.user_id = :userId " +
        "GROUP BY dp.people_id " +
        "ORDER BY p.name", nativeQuery = true)
    Page<PeopleDTO> findByPeopleAndCountByUserId(@Param("userId") Long userId, Pageable pageable);

}



// Interface to which result is projected
public interface PeopleDTO {

    String getName();

    Long getCount();

}

প্রস্তাবিত ইন্টারফেসের ক্ষেত্রগুলি অবশ্যই এই সত্তার ক্ষেত্রগুলির সাথে মেলে। অন্যথায় ফিল্ড ম্যাপিং ভাঙ্গতে পারে।

এছাড়াও যদি আপনি SELECT table.columnস্বরলিপি ব্যবহার করেন তবে সর্বদা উদাহরণ হিসাবে যেমন সত্ত্বার সাথে মিলে যাওয়া নামগুলি সংজ্ঞায়িত করে।


1
নেটিভ ক্যোয়ারী এবং অনুমানগুলি একসাথে ভাল হয় না।
কেভিন রাভ

1
আমি বেশ সঠিকভাবে কাজ করার জন্য ফিল্ড ম্যাপিংটি পেতে পারি না - সর্বাধিক মানগুলি নাল হিসাবে ফিরে আসতে থাকে
আয়ং

4

হাইবারনেটে আপনি সহজেই আপনার স্থানীয় ক্যোয়ারী মানচিত্র করতে এই কোডটি ব্যবহার করতে পারেন।

private List < Map < String, Object >> getNativeQueryResultInMap() {
String mapQueryStr = "SELECT * FROM AB_SERVICE three ";
Query query = em.createNativeQuery(mapQueryStr);
NativeQueryImpl nativeQuery = (NativeQueryImpl) query;
nativeQuery.setResultTransformer(AliasToEntityMapResultTransformer.INSTANCE);
List < Map < String, Object >> result = query.getResultList();
for (Map map: result) {
    System.out.println("after request  ::: " + map);
}
return result;}

2

হাইবারনেট ব্যবহার:

@Transactional(readOnly=true)
public void accessUser() {
EntityManager em = repo.getEntityManager();
    org.hibernate.Session session = em.unwrap(org.hibernate.Session.class);
    org.hibernate.SQLQuery q = (org.hibernate.SQLQuery) session.createSQLQuery("SELECT u.username, u.name, u.email, 'blabla' as passe, login_type as loginType FROM users u").addScalar("username", StringType.INSTANCE).addScalar("name", StringType.INSTANCE).addScalar("email", StringType.INSTANCE).addScalar("passe", StringType.INSTANCE).addScalar("loginType", IntegerType.INSTANCE)
        .setResultTransformer(Transformers.aliasToBean(User2DTO.class));

    List<User2DTO> userList = q.list();
}

2

রেজাল্টসেট ব্যবহার করে পুরানো স্টাইল

@Transactional(readOnly=true)
public void accessUser() {
    EntityManager em = this.getEntityManager();
    org.hibernate.Session session = em.unwrap(org.hibernate.Session.class);
    session.doWork(new Work() {
        @Override
        public void execute(Connection con) throws SQLException {
            try (PreparedStatement stmt = con.prepareStatement(
                    "SELECT u.username, u.name, u.email, 'blabla' as passe, login_type as loginType FROM users u")) {
                ResultSet rs = stmt.executeQuery();
                ResultSetMetaData rsmd = rs.getMetaData();
                for (int i = 1; i <= rsmd.getColumnCount(); i++) {
                    System.out.print(rsmd.getColumnName(i) + " (" + rsmd.getColumnTypeName(i) + ") / ");
                }
                System.out.println("");
                while (rs.next()) {
                    System.out.println("Found username " + rs.getString("USERNAME") + " name " + rs.getString("NAME") + " email " + rs.getString("EMAIL") + " passe " + rs.getString("PASSE") + " email " + rs.getInt("LOGIN_TYPE"));
                }
            }
        }
    });
}

1

যেহেতু অন্যরা ইতিমধ্যে সমস্ত সম্ভাব্য সমাধানগুলি উল্লেখ করেছে, তাই আমি আমার কাজের সমাধানটি ভাগ করছি।

আমার সাথে Postgres 9.4কাজ করার সময় Jackson,

//Convert it to named native query.
List<String> list = em.createNativeQuery("select cast(array_to_json(array_agg(row_to_json(a))) as text) from myschema.actors a")
                   .getResultList();

List<ActorProxy> map = new ObjectMapper().readValue(list.get(0), new TypeReference<List<ActorProxy>>() {});

আমি নিশ্চিত যে আপনি অন্যান্য ডাটাবেসের জন্য এটি সন্ধান করতে পারেন।

এছাড়াও এফওয়াইআই, জেপিএ 2.0 মানচিত্রের ফলাফলের ফলাফল


1

এটি এখানে ফিট করে কিনা তা নিশ্চিত না, তবে আমার অনুরূপ প্রশ্ন ছিল এবং আমার জন্য নিম্নলিখিত সহজ সমাধান / উদাহরণ খুঁজে পেয়েছি:

private EntityManager entityManager;
...
    final String sql = " SELECT * FROM STORE "; // select from the table STORE
    final Query sqlQuery = entityManager.createNativeQuery(sql, Store.class);

    @SuppressWarnings("unchecked")
    List<Store> results = (List<Store>) sqlQuery.getResultList();

আমার ক্ষেত্রে আমাকে স্ট্রিংগুলিতে অন্য কোথাও সংজ্ঞায়িত এসকিউএল অংশগুলি ব্যবহার করতে হয়েছিল, তাই আমি কেবল নামডাইভেটিভ কিওয়ারি ব্যবহার করতে পারি না।


যত তাড়াতাড়ি আমরা সত্তা ফিরে। অভিনব কিছু না। সমস্যাটি যখন আপনি কোনও পরিচালনাবিহীন POJO এ ফলাফলটি ম্যাপ করার চেষ্টা করেন।
ওলগুন কেয়া

1

রেজাল্টসেট ব্যবহার করে পুরানো স্টাইল

@Transactional(readOnly=true)
public void accessUser() {
    EntityManager em = this.getEntityManager();
    org.hibernate.Session session = em.unwrap(org.hibernate.Session.class);
    session.doWork(new Work() {
        @Override
        public void execute(Connection con) throws SQLException {
            try (PreparedStatement stmt = con.prepareStatement(
                    "SELECT u.username, u.name, u.email, 'blabla' as passe, login_type as loginType FROM users u")) {
                ResultSet rs = stmt.executeQuery();
                ResultSetMetaData rsmd = rs.getMetaData();
                for (int i = 1; i <= rsmd.getColumnCount(); i++) {
                    System.out.print(rsmd.getColumnName(i) + " (" + rsmd.getColumnTypeName(i) + ") / ");
                }
                System.out.println("");
                while (rs.next()) {
                    System.out.println("Found username " + rs.getString("USERNAME") + " name " + rs.getString("NAME") + " email " + rs.getString("EMAIL") + " passe " + rs.getString("PASSE") + " email " + rs.getInt("LOGIN_TYPE"));
                }
            }
        }
    });
}

1

আমরা নিম্নলিখিত উপায়ে ব্যবহার করে সমস্যার সমাধান করেছি:

   //Add actual table name here in Query
    final String sqlQuery = "Select a.* from ACTORS a"
    // add your entity manager here 
    Query query = entityManager.createNativeQuery(sqlQuery,Actors.class);
    //List contains the mapped entity data.
    List<Actors> list = (List<Actors>) query.getResultList();

0

জটিল SqlResultSetMapping ব্যবহার না করে নেটিভ ক্যোয়ারী থেকে ফলাফল পুনরুদ্ধার করতে সিওডো সত্তা হিসাবে একটি পজো ব্যবহারের জন্য নীচের উদাহরণটি দেখুন। আপনার পোজোতে কেবল দুটি টিকা প্রয়োজন, একটি খালি @ আইন এবং একটি ডামি @ আইডি d @ আইডিটি আপনার পছন্দের যে কোনও ক্ষেত্রে ব্যবহার করা যেতে পারে, একটি @ আইডি ফিল্ডে নকল কী থাকতে পারে তবে নালিকাগুলি থাকতে পারে না।

যেহেতু @Enity কোনও দৈহিক টেবিলকে মানচিত্র দেয় না, তাই এই পোজোকে ছদ্ম সত্তা বলা হয়।

পরিবেশ: এক্লিপসেলিংক ২.০.০-আরসি ১, জেপিএ -২.১.০, মাইএসকিএল-সংযোজক-জাভা -5.1.14

আপনি এখানে সম্পূর্ণ maven প্রকল্পটি ডাউনলোড করতে পারেন

নেটিভ কোয়েরি মাইএসকিএল নমুনা কর্মীদের উপর ভিত্তি করে তৈরি করা হয় ডিবি http://dev.mysql.com/doc/employee/en/employees-installation.html

persistence.xml

<?xml version="1.0" encoding="UTF-8"?><persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.1" 
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="jpa-mysql" transaction-type="RESOURCE_LOCAL">
    <class>org.moonwave.jpa.model.pojo.Employee</class>
    <properties>
        <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/employees" />
        <property name="javax.persistence.jdbc.user" value="user" />
        <property name="javax.persistence.jdbc.password" value="***" />
        <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
    </properties>
</persistence-unit>

Employee.java

package org.moonwave.jpa.model.pojo;

@Entity
public class Employee {

@Id
protected Long empNo;

protected String firstName;
protected String lastName;
protected String title;

public Long getEmpNo() {
    return empNo;
}
public void setEmpNo(Long empNo) {
    this.empNo = empNo;
}
public String getFirstName() {
    return firstName;
}
public void setFirstName(String firstName) {
    this.firstName = firstName;
}
public String getLastName() {
    return lastName;
}
public void setLastName(String lastName) {
    this.lastName = lastName;
}   
public String getTitle() {
    return title;
}
public void setTitle(String title) {
    this.title = title;
}
public String toString() {
    StringBuilder sb = new StringBuilder();
    sb.append("empNo: ").append(empNo);
    sb.append(", firstName: ").append(firstName);
    sb.append(", lastName: ").append(lastName);
    sb.append(", title: ").append(title);
    return sb.toString();
}
}

EmployeeNativeQuery.java

public class EmployeeNativeQuery {
private EntityManager em;
private EntityManagerFactory emf;

public void setUp() throws Exception {
    emf=Persistence.createEntityManagerFactory("jpa-mysql");
    em=emf.createEntityManager();
}
public void tearDown()throws Exception {
    em.close();
    emf.close();
}

@SuppressWarnings("unchecked")
public void query() {
    Query query = em.createNativeQuery("select e.emp_no as empNo, e.first_name as firstName, e.last_name as lastName," + 
            "t.title from employees e join titles t on e.emp_no = t.emp_no", Employee.class);
    query.setMaxResults(30);
    List<Employee> list = (List<Employee>) query.getResultList();
    int i = 0;
    for (Object emp : list) {
        System.out.println(++i + ": " + emp.toString());
    }
}

public static void main( String[] args ) {
    EmployeeNativeQuery test = new EmployeeNativeQuery();
    try {
        test.setUp();
        test.query();
        test.tearDown();
    } catch (Exception e) {
        System.out.println(e);
    }
}
}

1
যেহেতু আপনার list, অভিযোগের একটি তালিকা Employee, কেন আপনার প্রতিটি লুপটি কোনও ধরণের উপরে পুনরাবৃত্তি করছে Object? আপনি যদি নিজের প্রতিটি লুপটি লিখেন for(Employee emp : list)তবেই আপনি আবিষ্কার করতে পারবেন যে আপনার উত্তরটি ভুল এবং আপনার তালিকার বিষয়বস্তু কর্মচারী নয় এবং যে সতর্কবাণীটি আপনি চাপা দিয়েছিলেন তার উদ্দেশ্য ছিল এই সম্ভাব্য ভুল সম্পর্কে আপনাকে সতর্ক করার।
এডউইন ডালোরজো

@ সাপ্রেস ওয়ার্নিংস ("চেক না করা") List<Employee> list = (List<Employee>) query.getResultList();পরিবর্তনটি আরও ভাল for (Object emp : list)করার জন্য সতর্কতা দমন করতে ব্যবহৃত হয় for (Employee emp : list), তবে Object empতালিকাটি উদাহরণ হিসাবে না রাখলে কোনও ত্রুটি নেই List<Employee>। আমি গিট প্রকল্পে কোডটি পরিবর্তন করেছি তবে আপনার মন্তব্যটি মূল পোস্টের সাথে প্রাসঙ্গিক রাখতে এখানে নেই
জোনাথন এল

সমস্যাটি হ'ল আপনার ক্যোয়ারী কর্মসংস্থানের একটি তালিকা ফেরত দেয় না, তবে অবজেক্টের একটি অ্যারে। আপনার দমন করা সতর্কতা এটি লুকিয়ে রয়েছে। আপনি যে কোনও মুহুর্তে কোনও কর্মচারীতে রূপান্তরিত করার চেষ্টা করেছেন এমন মোমন্টোতে আপনি একটি ত্রুটি পাবেন, একটি ব্যতিক্রম ব্যতিক্রম।
এডউইন ডালোরজো

দেখুন Query query = em.createNativeQuery("select * ...", Employee.class);এবং অধ্যবস। আমি কেবল প্রকল্পটি ডাব্লু / ও ইস্যুটি পরীক্ষা করে দেখেছি। আপনি যদি স্থানীয়ভাবে মাইএসকিএল নমুনা কর্মীদের ডিবি সেটআপ করেন, আপনিও প্রকল্পটি চালাতে সক্ষম হবেন
জোনাথন এল

ওহ আমি এখন আপনি কি বলতে চাইছেন। তবে সেক্ষেত্রে আপনার উত্তর প্রশ্নটি সন্তুষ্ট করে না, কারণ এটি টার্গেট অবজেক্ট হিসাবে একটি নিয়মিত POJO ব্যবহার করার বিষয়ে ছিল এবং আপনার উত্তরটি ব্যবহার করছে Employeeযা আমি অনুমান করি যে এটি একটি সত্তা। তাই না?
এডউইন ডালোরজো

0

আপনি যদি বসন্ত ব্যবহার করছেন তবে আপনি ব্যবহার করতে পারেন org.springframework.jdbc.core.RowMapper

এখানে একটি উদাহরণ:

public List query(String objectType, String namedQuery)
{
  String rowMapper = objectType + "RowMapper";
  // then by reflection you can instantiate and use. The RowMapper classes need to follow the naming specific convention to follow such implementation.
} 

0

হাইবারনেট ব্যবহার:

@Transactional(readOnly=true)
public void accessUser() {
    EntityManager em = repo.getEntityManager();
    org.hibernate.Session session = em.unwrap(org.hibernate.Session.class);
    org.hibernate.SQLQuery q = (org.hibernate.SQLQuery) session.createSQLQuery("SELECT u.username, u.name, u.email, 'blabla' as passe, login_type as loginType FROM users u")
        .addScalar("username", StringType.INSTANCE).addScalar("name", StringType.INSTANCE)
        .addScalar("email", StringType.INSTANCE).addScalar("passe", StringType.INSTANCE)
        .addScalar("loginType", IntegerType.INSTANCE)
        .setResultTransformer(Transformers.aliasToBean(User2DTO.class));

    List<User2DTO> userList = q.list();
}

-1

এসকিউএল ক্যোয়ারিকে পোজো শ্রেণি সংগ্রহে রূপান্তর করার সহজ উপায়,

Query query = getCurrentSession().createSQLQuery(sqlQuery).addEntity(Actors.class);
List<Actors> list = (List<Actors>) query.list();
return list;

-1

আপনার যা যা প্রয়োজন তা হ'ল একটি কন্সট্রাক্টরের একটি ডিটিও:

public class User2DTO implements Serializable {

    /** pode ser email ou id do Google comecando com G ou F para Facebook */
    private String username;

    private String password;

    private String email;

    private String name;

    private Integer loginType;

    public User2DTO(Object...fields) {
        super();
        this.username = (String) fields[0];
        this.name = (String) fields[1];
        this.email = (String) fields[2];
        this.password = (String) fields[3];
        this.loginType = (Integer) fields[4];
    }

এবং এটি কল:

EntityManager em = repo.getEntityManager();
        Query q = em.createNativeQuery("SELECT u.username, u.name, u.email, 'blabla' as passe, login_type as loginType FROM users u");
        List<Object[]> objList = q.getResultList();
        List<User2DTO> ooBj = objList.stream().map(User2DTO::new).collect(Collectors.toList());

একটি নতুন কলাম যুক্ত করুন এবং কোডটি ভেঙে যাবে।
ডিসিশ

-2

ব্যবহার DTO Design Pattern। এটি ব্যবহৃত হয়েছিল EJB 2.0। সত্তা ধারক পরিচালিত ছিল। DTO Design Patternএই সমস্যাটি সমাধান করতে ব্যবহৃত হয়। তবে, অ্যাপ্লিকেশনটি বিকাশ করা Server Sideএবং Client Sideআলাদাভাবে করা গেলে এটি এখন ব্যবহার করা যেতে পারে । এনটোটেশন দিয়ে পাস / ফিরতে না চাইলে DTOব্যবহৃত হয় ।Server sideEntityClient Side

ডিটিও উদাহরণ:

PersonEntity.java

@Entity
public class PersonEntity {
    @Id
    private String id;
    private String address;

    public PersonEntity(){

    }
    public PersonEntity(String id, String address) {
        this.id = id;
        this.address = address;
    }
    //getter and setter

}

PersonDTO.java

public class PersonDTO {
    private String id;
    private String address;

    public PersonDTO() {
    }
    public PersonDTO(String id, String address) {
        this.id = id;
        this.address = address;
    }

    //getter and setter 
}

DTOBuilder.java

public class DTOBuilder() {
    public static PersonDTO buildPersonDTO(PersonEntity person) {
        return new PersonDTO(person.getId(). person.getAddress());
    }
}

সত্তা বিল্ডার.জভা <- এটি প্রয়োজন হতে পারে

public class EntityBuilder() {
    public static PersonEntity buildPersonEntity(PersonDTO person) {
        return new PersonEntity(person.getId(). person.getAddress());
    }
}

4
উত্তরের জন্য ধন্যবাদ। এখানে আমার ডিটিও প্যাটার্ন দরকার নেই। আমার প্রয়োজনীয়তা ক্লায়েন্টের কাছ থেকে টিকা বিশদটি গোপন করা নয়। সুতরাং আমার অ্যাপটিতে আরও একটি পজো তৈরি করার দরকার নেই। আমার প্রয়োজনটি ফলাফলটি QA পোজোতে সেট করা যা কোনও জাভা সত্তা নয় তবে সাধারণ পোজো শ্রেণীর ফলাফল সেট কলামগুলির মতো একই ক্ষেত্র রয়েছে।
গুঞ্জন শাহ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.