স্প্রিং জেপিএ নির্দিষ্ট কলামগুলি নির্বাচন করছে


146

আমি সমস্ত ডাটাবেস ক্রিয়াকলাপ সম্পাদন করতে স্প্রিং জেপিএ ব্যবহার করছি। তবে আমি জানি না কীভাবে স্প্রিং জেপিএতে কোনও টেবিল থেকে নির্দিষ্ট কলামগুলি নির্বাচন করতে হয়?

উদাহরণ স্বরূপ:
SELECT projectId, projectName FROM projects



জেপিএর নির্দিষ্ট ক্ষেত্রগুলির সন্ধান না করার পেছনের ধারণাটি হ'ল টেবিলের এক সারি থেকে একটি কলাম বা সমস্ত কলাম আনতে ব্যয় (দক্ষতার ভিত্তিতে) সমান।
দেশদার

7
@ ডিজর্ডার - খরচ সর্বদা এক হয় না। এটি সহজ, আদিম ধরণের ডেটাটাইপগুলির পক্ষে খুব বড় বিষয় নয় তবে আমি এই পৃষ্ঠাটিতে শেষ হওয়ার কারণটি আমি লক্ষ্য করেছি যে একটি সাধারণ "তালিকাগুলির নথি" কোয়েরিটি ধীরে চলছে। সেই সত্তার একটি বিএলওবি কলাম রয়েছে (এটি ফাইল আপলোড / স্টোরেজগুলির জন্য প্রয়োজন) এবং আমার সন্দেহ হয় যে এটি ধীর গতির কারণ এটি দস্তাবেজগুলির তালিকা তৈরি করার জন্য প্রয়োজনীয় না হলেও এটি মেমোরিতে BLOB লোড করছে।
jm0

@ jm0 যতদূর আপনি মনে আছে, কতগুলি টেবিলের বিএলওবি কলাম ছিল?
দেশর্ডার

1
@ ডিজর্ডারটি কেবল একটি টেবিল ছিল তবে আমি একটি "তালিকা" ফাংশন করছিলাম (মাল্টিও - প্রদত্ত আইডি দ্বারা নির্মিত সমস্ত ডক্সকে তালিকাভুক্ত করুন)। আমি এই সমস্যাটি লক্ষ্য করার একমাত্র কারণ হ'ল এই সাধারণ তালিকাগুলিটি বেশ কয়েক সেকেন্ড সময় নিয়েছে, অন্য টেবিলে আরও জটিল প্রশ্নগুলি প্রায় তাত্ক্ষণিকভাবে ঘটছিল। একবার আমি বুঝতে পেরেছিলাম, সারি যুক্ত হওয়ার সাথে সাথে এটি আরও বেশি ক্ষতিগ্রস্থ হতে পারে কারণ স্প্রিং জেপিএ প্রতিটি বিএলওবি স্মৃতিতে লোড করছে এমনকি সেগুলি ব্যবহৃত হয় না। আমি বসন্তের তথ্যের জন্য একটি নিখুঁত সমাধান খুঁজে পেয়েছি (নীচে পোস্ট করা হয়েছে) তবে আমার কাছে মনে হয় আমার কাছে আরও ভাল একটি আছে যা খাঁটি জেপিএ টিকা আছে, আমি যদি টিএমআরডব পোস্ট করি তবে এটি কার্যকর হবে
jm0

উত্তর:


75

আপনি সেট করতে পারেন nativeQuery = trueমধ্যে @QueryA থেকে টীকা Repositoryভালো শ্রেণী:

public static final String FIND_PROJECTS = "SELECT projectId, projectName FROM projects";

@Query(value = FIND_PROJECTS, nativeQuery = true)
public List<Object[]> findProjects();

মনে রাখবেন যে আপনাকে নিজেরাই ম্যাপিং করতে হবে। আপনার যদি কেবলমাত্র এই দুটি মানের প্রয়োজন না হয় তবে কেবল নিয়মিত ম্যাপযুক্ত চেহারাটি ব্যবহার করা সম্ভবত এটির পক্ষে সহজ:

public List<Project> findAll()

স্প্রিং ডেটা ডক্সগুলিও সম্ভবত এটি মূল্যবান ।


5
দেশীয় প্রশ্নের প্রয়োজন নেই no আপনার এগুলি ব্যবহার করা এড়ানো উচিত কারণ তারা জেপিকিউএল এর সুবিধাগুলি নষ্ট করে। অ্যাটলস উত্তর দেখুন।
phil294

1
আমার জন্য আমাকে প্রথম বৈশিষ্ট্যটি (উপরে FIND_PROJECTS) গুণাবলীর সাথে যোগ্যতা অর্জন করতে valueহয়েছিল (অতএব এটি যদি আমার কোড হয় তবে আমি এটি @Query(value = FIND_PROJECTS, nativeQuery = true)
লিখতাম

172

আপনি স্প্রিং ডেটা জেপিএ (ডক) থেকে অনুমানগুলি ব্যবহার করতে পারেন । আপনার ক্ষেত্রে, ইন্টারফেস তৈরি করুন:

interface ProjectIdAndName{
    String getId();
    String getName();
}

এবং আপনার ভাণ্ডারে নিম্নলিখিত পদ্ধতি যুক্ত করুন

List<ProjectIdAndName> findAll();

11
এটি একটি পরিষ্কার সমাধান। এটিতে বয়লার টেমপ্লেট থাকতে পারে তবে ইন্টারফেসটি সত্তার অভ্যন্তর শ্রেণি হতে পারে। এটি বেশ পরিষ্কার করা।
আইসম্যান

1
দুর্দান্ত, শুধু মনে রাখবেন আপনার
সত্তার

1
অনুমান করা ইন্টারফেসটি কোথায় যায়? এর নিজস্ব ফাইলে বা এটিকে সর্বজনীন ইন্টারফেসে অন্তর্ভুক্ত করা যেতে পারে যা সম্পূর্ণ সত্তার বৈশিষ্ট্য ফেরত দেয়?
মিচো রিজো

8
এই সমাধানটি JpaRepository প্রসারিত করার সময় কাজ করে না, কেউ কি একটি workaround জানেন?
জার্মান

4
আপনি FindAll () ব্যবহার করতে পারবেন না; যেহেতু এটি জেআরপিওসিটোরিস পদ্ধতির সাথে সংঘর্ষ করবে। আপনাকে <ProjectIdAndName> FindAllBy () এর মতো কিছু ব্যবহার করতে হবে;
কোড_মোড

137

আমি সিনট্যাক্সটি বিশেষত পছন্দ করি না (এটি দেখতে কিছুটা হ্যাকি লাগছে ...) তবে এটি সর্বাধিক মার্জিত সমাধান যা আমি সন্ধান করতে পেরেছিলাম (এটি জেপিএ সংগ্রহস্থল শ্রেণিতে একটি কাস্টম জেপিকিউএল কোয়েরি ব্যবহার করে):

@Query("select new com.foo.bar.entity.Document(d.docId, d.filename) from Document d where d.filterCol = ?1")
List<Document> findDocumentsForListing(String filterValue);

তবে অবশ্যই, আপনাকে কেবল কনস্ট্রাক্টর সরবরাহ করতে হবে Documentযা গ্রহণ করে docIdএবং filenameকনস্ট্রাক্টর আরগ হিসাবে।


9
(এবং বিটিডব্লু আমি যাচাই করেছি, "ডকুমেন্ট" আমদানি করা হলে আপনাকে পুরোপুরি যোগ্য
শ্রেণীবদ্ধের নাম দেওয়ার দরকার নেই

এটি গ্রহণযোগ্য উত্তর হওয়া উচিত। এটি নিখুঁতভাবে কাজ করে এবং সত্যই কেবল প্রয়োজনীয় ক্ষেত্রগুলি নির্বাচন করে।
যোনাতন উইলকফ

1
অপ্রয়োজনীয় ক্ষেত্রগুলিও অন্তর্ভুক্ত করা হয়েছে, তবে 'নাল' মানের সাথে কী এই ক্ষেত্রগুলি মেমরির অধিকারে থাকবে?
গ্যাবলার

হ্যাঁ তবে এতটা ন্যূনতম যে এর বেশিরভাগ ক্ষেত্রেই এটিকে ইঞ্জিনিয়ার করার চেষ্টা করা সত্যই হাস্যকর হবে - স্ট্যাকওভারফ্লো / প্রশ্নগুলি / ২৪৩০65৫৫/ … আপনাকে এই ক্ষেত্রগুলি ছাড়াই বিশেষায়িত লাইটওয়েট অবজেক্ট তৈরি করতে হবে এবং সেগুলিকে একই নির্দেশ করতে হবে টেবিল? কোন আইএমও ওআরএম ব্যবহার করার সময় এবং তাদের সম্পর্কের জন্য লাভবান হওয়ার ক্ষেত্রে অনাকাঙ্ক্ষিত ... হাইপার-অপটিমাইজেশন সম্ভবত কিছু হালকা কোয়েরি ডিএসএল ব্যবহার করে এবং সরাসরি ডিটিওতে ম্যাপিংয়ের ক্ষেত্রে আরও বেশি হতে পারে, এবং তারপরেও আমি মনে করি রিডানডেন্সিকে নিরুত্সাহিত করা হয়েছে
jm0

2
jm0 এটি পুরোপুরি যোগ্য শ্রেণীবদ্ধতা ছাড়াই আমার পক্ষে কাজ করে না, যদিও এটি আমদানি করা হয়েছিল। যদিও এটি সফলভাবে সংকলন করেছে।
হাইজেনবার্গ

20

আমার পরিস্থিতিতে আমার কেবল জসন ফলাফল প্রয়োজন এবং এটি আমার পক্ষে কাজ করে:

public interface SchoolRepository extends JpaRepository<School,Integer> {
    @Query("select s.id, s.name from School s")
    List<Object> getSchoolIdAndName();
}

নিয়ামক মধ্যে:

@Autowired
private SchoolRepository schoolRepository;

@ResponseBody
@RequestMapping("getschoolidandname.do")
public List<Object> getSchool() {
    List<Object> schools = schoolRepository.getSchoolIdAndName();
    return schools;
}

2
Objectএমআরপি অনুসারে বর্ণিত কাস্টম ইন্টারফেসের পরিবর্তে আপনার উচিত ।
নির্দ্বিধায়

14

আমার ক্ষেত্রে আমি ক্ষেত্রগুলি প্রয়োজন নেই সেগুলি ছাড়া একটি পৃথক সত্তা শ্রেণি তৈরি করেছি (কেবলমাত্র প্রয়োজনীয় ক্ষেত্রগুলির সাথে)।

একই সারণিতে সত্তাটি মানচিত্র করুন। এখন যখন সমস্ত কলামগুলির প্রয়োজন হয় আমি পুরানো সত্তাটি ব্যবহার করি, যখন কেবলমাত্র কিছু কলামের প্রয়োজন হয়, আমি লাইট সত্তাটি ব্যবহার করি।

যেমন

@Entity
@Table(name = "user")
Class User{
         @Column(name = "id", unique=true, nullable=false)
         int id;
         @Column(name = "name", nullable=false)
         String name;
         @Column(name = "address", nullable=false)
         Address address;
}

আপনি এর মতো কিছু তৈরি করতে পারেন:

@Entity
@Table(name = "user")
Class UserLite{
         @Column(name = "id", unique=true, nullable=false)
         int id;
         @Column(name = "name", nullable=false)
         String name;
}

আপনি যখন কলামগুলি আনার জন্য জানেন (এবং এটি পরিবর্তন হবে না) এটি কাজ করে।

আপনার কলামগুলি গতিশীলভাবে সিদ্ধান্ত নেওয়ার প্রয়োজন হলে কাজ করবে না।


হাই স্যাচিন, আপনারা উপরে উল্লিখিত মত আমি সত্তাটি তৈরি করব কিনা তা নিয়ে আমার সন্দেহ আছে। যখন জেপিএ চলবে এবং এটি ব্যবহারকারীর নামের সাথে সারণী তৈরি করার চেষ্টা করবে। কোন সত্তা ব্যবহার করবে।
ব্যবহারকারী 3364549

3
জেপিএ দিয়ে কখনই কোনও টেবিল তৈরি করবেন না, ডিবিতে ম্যানুয়ালি আপনার টেবিল তৈরি করুন, বিশ্বকে আপত্তি জানাতে জেপিএ ব্যবহার করুন map
শচীন শর্মা

আপনি এখানে উত্তরাধিকার ব্যবহার করতে পারবেন না কেন?
ডেডব্যাগ

8

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

আপনার প্রশ্নের উত্তর ব্যবহার করা যেতে পারে

JPAQuery query = new JPAQuery(entityManager);
List<Tuple> result = query.from(projects).list(project.projectId, project.projectName);
for (Tuple row : result) {
 System.out.println("project ID " + row.get(project.projectId));
 System.out.println("project Name " + row.get(project.projectName)); 
}}

সত্তা পরিচালকটি অনুমোদিত হতে পারে এবং আপনি সর্বদা অবজেক্ট এবং ক্লাজের সাথে কাজ না করে * কিউএল ভাষা ব্যবহার করবেন।

আপনি লিঙ্কটিতে দেখতে পারেন শেষ পছন্দটি প্রায় আমার কাছে মনে হয়, আরও মার্জিত, এটি হ'ল ফলাফলের জন্য ডিটিও ব্যবহার করে। আপনার উদাহরণে প্রয়োগ করুন যা হবে:

JPAQuery query = new JPAQuery(entityManager);
QProject project = QProject.project;
List<ProjectDTO> dtos = query.from(project).list(new QProjectDTO(project.projectId, project.projectName));

প্রকল্পডিটিও হিসাবে সংজ্ঞা দেওয়া হচ্ছে:

class ProjectDTO {

 private long id;
 private String name;
 @QueryProjection
 public ProjectDTO(long projectId, String projectName){
   this.id = projectId;
   this.name = projectName;
 }
 public String getProjectId(){ ... }
 public String getProjectName(){....}
}

5

নতুন বসন্ত সংস্করণগুলির সাহায্যে কেউ নিম্নলিখিত হিসাবে করতে পারে:

নেটিভ কোয়েরি ব্যবহার না করা হলে নীচের মতো এটি করা যেতে পারে:

public interface ProjectMini {
    String getProjectId();
    String getProjectName();
}

public interface ProjectRepository extends JpaRepository<Project, String> { 
    @Query("SELECT p FROM Project p")
    List<ProjectMini> findAllProjectsMini();
}

নেটিভ ক্যোয়ারী ব্যবহার করে নীচের মত একই কাজ করা যেতে পারে:

public interface ProjectRepository extends JpaRepository<Project, String> { 
    @Query(value = "SELECT projectId, projectName FROM project", nativeQuery = true)
    List<ProjectMini> findAllProjectsMini();
}

বিশদ জন্য ডক্স পরীক্ষা করুন


4

আমার মতে এটি দুর্দান্ত সমাধান:

interface PersonRepository extends Repository<Person, UUID> {

    <T> Collection<T> findByLastname(String lastname, Class<T> type);
}

এবং এটি যেমন ব্যবহার

void someMethod(PersonRepository people) {

  Collection<Person> aggregates =
    people.findByLastname("Matthews", Person.class);

  Collection<NamesOnly> aggregates =
    people.findByLastname("Matthews", NamesOnly.class);
}

সংগ্রহের পরিবর্তে <T> তালিকাটি কেন ফেরানো হবে না?!
আবদুল্লাহ খান

@ আবদুল্লাহ খান, কারণ ফলাফলের সবসময় কোনও আদেশ নাও থাকতে পারে।
রবি সানওয়াল

4

স্প্রিং ডেটা জেপিএ ব্যবহার করে ডাটাবেস থেকে নির্দিষ্ট কলামগুলি নির্বাচন করার ব্যবস্থা রয়েছে

---- ডিএওআইএমপিএল ----

@Override
    @Transactional
    public List<Employee> getAllEmployee() throws Exception {
    LOGGER.info("Inside getAllEmployee");
    List<Employee> empList = empRepo.getNameAndCityOnly();
    return empList;
    }

---- রেপো ----

public interface EmployeeRepository extends CrudRepository<Employee,Integer> {
    @Query("select e.name, e.city from Employee e" )
    List<Employee> getNameAndCityOnly();
}

এটি আমার ক্ষেত্রে 100% কাজ করেছে। ধন্যবাদ।


2

আপনি জেপিকিউএল ব্যবহার করতে পারেন:

TypedQuery <Object[]> query = em.createQuery(
  "SELECT p.projectId, p.projectName FROM projects AS p", Object[].class);

List<Object[]> results = query.getResultList();

অথবা আপনি স্থানীয় এসকিএল কোয়েরি ব্যবহার করতে পারেন।

Query query = em.createNativeQuery("sql statement");
List<Object[]> results = query.getResultList();

2

nullস্থানীয় বর্গক্ষেত্রে ক্ষেত্রের মান হিসাবে নির্দিষ্ট করা সম্ভব ।

@Query(value = "select p.id, p.uid, p.title, null as documentation, p.ptype " +
            " from projects p " +
            "where p.uid = (:uid)" +
            "  and p.ptype = 'P'", nativeQuery = true)
Project findInfoByUid(@Param("uid") String uid);

2

আপনি আপনার সংগ্রহস্থল ইন্টারফেস ক্লাসে নীচের কোডটি প্রয়োগ করতে পারেন।

সত্তার নাম অর্থ প্রকল্পের মতো আপনার ডাটাবেস সারণির নাম। এবং তালিকার অর্থ হল প্রকল্পগুলি আপনার প্রকল্পগুলির সত্তা শ্রেণি।

@Query(value="select p from #{#entityName} p where p.id=:projectId and p.projectName=:projectName")

List<Project> findAll(@Param("projectId") int projectId, @Param("projectName") String projectName);

0

নেটিভ ক্যোয়ারী ব্যবহার:

Query query = entityManager.createNativeQuery("SELECT projectId, projectName FROM projects");
List result = query.getResultList();

0

আপনি @ জম্বি দ্বারা প্রস্তাবিত উত্তরটি ব্যবহার করতে পারেন এবং:

  • সত্তা শ্রেণীর বাইরে, একটি পৃথক ফাইলে ইন্টারফেস রাখুন;
  • নেটিভ কোয়েরি ব্যবহার করুন বা না (পছন্দটি আপনার প্রয়োজনের উপর নির্ভরশীল);
  • findAll()এই উদ্দেশ্যটির জন্য পদ্ধতিটিকে ওভাররাইড করবেন না তবে নিজের পছন্দের নামটি ব্যবহার করুন;
  • Listআপনার নতুন ইন্টারফেস (উদাঃ List<SmallProject>) এর সাথে প্যারামিট্রাইজ করা ফিরে আসতে ভুলবেন না ।
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.