<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Troy</title>
    <description>The latest articles on DEV Community by Troy (@troyzhxu).</description>
    <link>https://dev.to/troyzhxu</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1648997%2F77bd9f25-db1e-493a-887f-1859de17e612.png</url>
      <title>DEV Community: Troy</title>
      <link>https://dev.to/troyzhxu</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/troyzhxu"/>
    <language>en</language>
    <item>
      <title>REST-style GraphQL — one line of Java handles filtering + sorting + pagination + stats + CSV export.</title>
      <dc:creator>Troy</dc:creator>
      <pubDate>Sat, 25 Jul 2026 16:45:53 +0000</pubDate>
      <link>https://dev.to/troyzhxu/rest-style-graphql-one-line-of-java-handles-filtering-sorting-pagination-stats-csv-export-3598</link>
      <guid>https://dev.to/troyzhxu/rest-style-graphql-one-line-of-java-handles-filtering-sorting-pagination-stats-csv-export-3598</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;(Demo's in Chinese but you'll get the idea in 30 seconds) 👇&lt;br&gt;
&lt;a href="https://demo-bs.zhxu.cn/" rel="noopener noreferrer"&gt;https://demo-bs.zhxu.cn/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A backend engineer's confession: you just wrote 100 lines of Java code to do exactly one thing — glue a few HTTP parameters into a SQL string.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  One Page of Requirements
&lt;/h2&gt;

&lt;p&gt;My PM sent me a mockup. Pretty standard admin panel stuff:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Paginated table&lt;/li&gt;
&lt;li&gt;Four filter fields at the top: name, age range, department, hire date&lt;/li&gt;
&lt;li&gt;Sort by any column&lt;/li&gt;
&lt;li&gt;Footer stats: total count, average age&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;"Easy, right? Can we ship this afternoon?" he asked.&lt;/p&gt;

&lt;p&gt;"Sure," I said.&lt;/p&gt;

&lt;p&gt;Then I opened IntelliJ.&lt;/p&gt;




&lt;h2&gt;
  
  
  If You Use MyBatis, Here's What the Next 30 Minutes Looks Like
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;select&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"searchUsers"&lt;/span&gt; &lt;span class="na"&gt;resultType=&lt;/span&gt;&lt;span class="s"&gt;"UserVO"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  SELECT u.*, d.name as deptName
  FROM user u LEFT JOIN dept d ON u.dept_id = d.id
  &lt;span class="nt"&gt;&amp;lt;where&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;if&lt;/span&gt; &lt;span class="na"&gt;test=&lt;/span&gt;&lt;span class="s"&gt;"name != null and name != ''"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      AND u.name LIKE CONCAT('%', #{name}, '%')
    &lt;span class="nt"&gt;&amp;lt;/if&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;if&lt;/span&gt; &lt;span class="na"&gt;test=&lt;/span&gt;&lt;span class="s"&gt;"ageMin != null"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      AND u.age &amp;gt;= #{ageMin}
    &lt;span class="nt"&gt;&amp;lt;/if&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;if&lt;/span&gt; &lt;span class="na"&gt;test=&lt;/span&gt;&lt;span class="s"&gt;"ageMax != null"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      AND u.age &lt;span class="ni"&gt;&amp;amp;lt;&lt;/span&gt;= #{ageMax}
    &lt;span class="nt"&gt;&amp;lt;/if&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;if&lt;/span&gt; &lt;span class="na"&gt;test=&lt;/span&gt;&lt;span class="s"&gt;"dept != null and dept != ''"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      AND d.name = #{dept}
    &lt;span class="nt"&gt;&amp;lt;/if&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;if&lt;/span&gt; &lt;span class="na"&gt;test=&lt;/span&gt;&lt;span class="s"&gt;"entryDateStart != null"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      AND u.entry_date &amp;gt;= #{entryDateStart}
    &lt;span class="nt"&gt;&amp;lt;/if&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;if&lt;/span&gt; &lt;span class="na"&gt;test=&lt;/span&gt;&lt;span class="s"&gt;"entryDateEnd != null"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      AND u.entry_date &lt;span class="ni"&gt;&amp;amp;lt;&lt;/span&gt;= #{entryDateEnd}
    &lt;span class="nt"&gt;&amp;lt;/if&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/where&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;if&lt;/span&gt; &lt;span class="na"&gt;test=&lt;/span&gt;&lt;span class="s"&gt;"sortField != null and sortOrder != null"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    ORDER BY ${sortField} ${sortOrder}
  &lt;span class="nt"&gt;&amp;lt;/if&amp;gt;&lt;/span&gt;
  LIMIT #{offset}, #{size}
&lt;span class="nt"&gt;&amp;lt;/select&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And you're not done. You still need: a stats SQL, a Controller to parse parameters, a Service layer for pagination logic, a Mapper interface, a VO class just to hold the results — plus careful &lt;code&gt;${}&lt;/code&gt; sanitization to prevent SQL injection.&lt;/p&gt;

&lt;p&gt;Four filter conditions. Almost 100 lines of code.&lt;/p&gt;

&lt;p&gt;Then the PM says: "Oh, by the way — make department multi-select. And add a gender filter."&lt;/p&gt;

&lt;p&gt;You take a deep breath and keep writing.&lt;/p&gt;

&lt;p&gt;This isn't a MyBatis problem. Try JPA — you won't suffer any less:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;Specification&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;spec&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cb&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Predicate&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;predicates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
  &lt;span class="nc"&gt;Join&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Department&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;deptJoin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;join&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"dept"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;JoinType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;LEFT&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;StringUtils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isNotBlank&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;predicates&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;like&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="s"&gt;"%"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"%"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ageMin&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;predicates&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ge&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"age"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="n"&gt;ageMin&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ageMax&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;predicates&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;le&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"age"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="n"&gt;ageMax&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;StringUtils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isNotBlank&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dept&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;predicates&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;equal&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;deptJoin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="n"&gt;dept&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;cb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;and&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;predicates&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toArray&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Predicate&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;]));&lt;/span&gt;
&lt;span class="o"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;MyBatis wraps if-else in XML. JPA wraps if-else in &lt;code&gt;Predicate&lt;/code&gt; chains. Same problem, different syntax — &lt;strong&gt;you're still manually translating parameters into query conditions, line by line.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In 2026, frontend devs are doing vibe coding — describe intent, let tools handle the details. Meanwhile, backend list queries are still stuck in the artisanal stone age: hand-written XML, hand-stitched Predicates, hand-typed if-else chains. Not because we want to. Because there was never a tool that let us vibe.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The root cause of all this pain: you've mashed "declaration" and "execution" together.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  A Different Mindset
&lt;/h2&gt;

&lt;p&gt;Let's step back for a second.&lt;/p&gt;

&lt;p&gt;Your database tables are already defined. What users want to search is up to them.&lt;/p&gt;

&lt;p&gt;So why do &lt;em&gt;you&lt;/em&gt; — the translator between HTTP parameters and SQL — have to write every single if-else by hand?&lt;/p&gt;

&lt;p&gt;What if a smart middle layer existed that just… knew?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It knows what fields your entity has → that's your &lt;strong&gt;search boundary&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;It knows what parameters the frontend sent → that's your &lt;strong&gt;search intent&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Combine the two → generate the SQL&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This idea isn't mine. In the API world, it has a name:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;GraphQL&lt;/strong&gt; — clients specify what fields they want. The server returns exactly those fields. One request replaces multiple REST calls.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So… what about list queries?&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;GraphQL&lt;/th&gt;
&lt;th&gt;Bean Searcher&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Domain&lt;/td&gt;
&lt;td&gt;API data queries&lt;/td&gt;
&lt;td&gt;Database list retrieval&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Client controls&lt;/td&gt;
&lt;td&gt;Which fields to return&lt;/td&gt;
&lt;td&gt;Which fields + filters + sort order + page size&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Protocol&lt;/td&gt;
&lt;td&gt;POST + GraphQL body&lt;/td&gt;
&lt;td&gt;Standard HTTP params (GET/POST)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Core idea&lt;/td&gt;
&lt;td&gt;Declare what data you want&lt;/td&gt;
&lt;td&gt;Declare search boundary, let params drive the query&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Adoption cost&lt;/td&gt;
&lt;td&gt;Change your API layer, add schema&lt;/td&gt;
&lt;td&gt;One dependency. Zero refactoring.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In one sentence: &lt;strong&gt;GraphQL lets the frontend control data fields in one request. Bean Searcher lets the frontend control filtering, sorting, pagination, and stats — using the URL params you already know.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The GraphQL of List Retrieval
&lt;/h2&gt;

&lt;p&gt;You define one entity:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@SearchBean&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tables&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"user u, dept d"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;where&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"u.dept_id = d.id"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;autoMapTo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"u"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserVO&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Integer&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;gender&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="nd"&gt;@DbField&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"d.name"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;deptName&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;LocalDate&lt;/span&gt; &lt;span class="n"&gt;entryDate&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// getters &amp;amp; setters...&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, the entire search endpoint is &lt;strong&gt;one line of code&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@GetMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/user/search"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;SearchResult&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;UserVO&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HttpServletRequest&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;beanSearcher&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;search&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;UserVO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;MapUtils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;flat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getParameterMap&lt;/span&gt;&lt;span class="o"&gt;()));&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Frontend sends a GET request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET /user/search?name=Li&amp;amp;age-0=20&amp;amp;age-1=30&amp;amp;age-op=bt&amp;amp;sort=age&amp;amp;order=desc
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"dataList"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Li Wei"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"age"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"deptName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Engineering"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"entryDate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2023-03-01"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Li Ming"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"age"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;28&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"deptName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Product"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"entryDate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2022-11-15"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"totalCount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;47&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"summaries"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1350&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Pagination. Table joins. Multi-condition filtering. Sorting. Stats. One endpoint. Everything.&lt;/strong&gt; No XML. No if-else. No VO conversion layer.&lt;/p&gt;

&lt;p&gt;This is &lt;a href="https://github.com/troyzhxu/bean-searcher" rel="noopener noreferrer"&gt;Bean Searcher&lt;/a&gt; — a framework I've been using for three years and can't stop recommending.&lt;/p&gt;




&lt;h2&gt;
  
  
  What It Actually Does
&lt;/h2&gt;

&lt;p&gt;One sentence explains 90% of the code it saves:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Entity classes declare the search boundary. HTTP parameters drive the query logic.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;This is vibe coding for list queries.&lt;/strong&gt; You declare "what can be searched." The frontend declares "what should be searched." All the translation in between — the framework handles it.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Traditional (MyBatis / JPA)&lt;/th&gt;
&lt;th&gt;Bean Searcher&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Define filter conditions&lt;/td&gt;
&lt;td&gt;Write &lt;code&gt;&amp;lt;if&amp;gt;&lt;/code&gt; in XML / stitch &lt;code&gt;QueryWrapper&lt;/code&gt; in Java&lt;/td&gt;
&lt;td&gt;Parameter names map directly to field names&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Add a new filter&lt;/td&gt;
&lt;td&gt;Change XML / Java code → recompile → redeploy&lt;/td&gt;
&lt;td&gt;Frontend sends a new parameter. &lt;strong&gt;Zero backend changes.&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multi-table joins&lt;/td&gt;
&lt;td&gt;Hand-write JOIN SQL&lt;/td&gt;
&lt;td&gt;Entity class declares relationships&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Return results&lt;/td&gt;
&lt;td&gt;Need a VO conversion layer&lt;/td&gt;
&lt;td&gt;The SearchBean &lt;em&gt;is&lt;/em&gt; the VO&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Security&lt;/td&gt;
&lt;td&gt;Write your own validation&lt;/td&gt;
&lt;td&gt;Anti-injection, pagination caps, deep-offset throttling — all on by default&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A metaphor: &lt;strong&gt;traditional ORMs are imperative&lt;/strong&gt; — you tell the framework every step. &lt;strong&gt;Bean Searcher is declarative&lt;/strong&gt; — you declare the boundary (what fields exist), and the frontend declares the intent (what to filter/sort/paginate).&lt;/p&gt;

&lt;p&gt;You're not writing queries anymore. You're &lt;strong&gt;declaring search boundaries&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Question You're Probably Thinking
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;"Doesn't this force the frontend to pass too many parameters?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I get this question constantly. The answer: &lt;strong&gt;how many parameters the frontend sends depends on product complexity, not on your backend framework. Period.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If the product only needs a fuzzy search box? Frontend sends &lt;code&gt;?name=Li&lt;/code&gt;. That's it. No &lt;code&gt;name-op&lt;/code&gt;. No &lt;code&gt;name-ic&lt;/code&gt;. You can even use it &lt;strong&gt;with zero annotations&lt;/strong&gt; — a plain POJO gets its fields auto-mapped to database columns (camelCase → snake_case).&lt;/p&gt;

&lt;p&gt;Remember: annotations are for &lt;strong&gt;constraints and fine-tuning&lt;/strong&gt;, not mandatory setup. A single-table entity is searchable out of the box, no annotations required.&lt;/p&gt;




&lt;h2&gt;
  
  
  Is It the Enemy of MyBatis/JPA?
&lt;/h2&gt;

&lt;p&gt;Absolutely not.&lt;/p&gt;

&lt;p&gt;MyBatis handles writes. Bean Searcher handles list reads. Different tools, different jobs, peaceful coexistence.&lt;/p&gt;

&lt;p&gt;Just as GraphQL wasn't created to kill REST — it just makes API queries more flexible — Bean Searcher wasn't created to kill MyBatis. It just makes list retrieval stop being painful.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;When to use&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;MyBatis / JPA&lt;/td&gt;
&lt;td&gt;Writes, transactions, complex business logic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bean Searcher&lt;/td&gt;
&lt;td&gt;Admin dashboards, data exports, report queries, any "dynamic multi-filter" scenario&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The relationship&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Complementary, not competing. Just add one dependency.&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Real Project Experience
&lt;/h2&gt;

&lt;p&gt;I've used Bean Searcher in three production projects (Spring Boot 2/3/4, Solon 3/4). The biggest change isn't "less code" — it's a &lt;strong&gt;different way of thinking&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Before: I'd get a list query requirement and my brain would go "OK, how do I write this SQL? How do I stitch the parameters? What object do I pass for pagination? What about sorting?"&lt;/p&gt;

&lt;p&gt;Now: I get the same requirement and think "What fields does the page need? Which tables do they come from? Which fields should the frontend be able to filter on?"&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You stop being a SQL stitcher. You become a domain modeler.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;2026's hottest term is vibe coding — describe your intent, let tools handle the details. Frontend devs have Cursor, v0, and bolt to vibe with. Why should backend list queries still be done the old-fashioned way?&lt;/p&gt;

&lt;p&gt;When I explain this to colleagues, their first reaction is always the same: "So it's like… GraphQL, but for Java backends?"&lt;/p&gt;

&lt;p&gt;"Exactly. Or put another way — it's vibe coding for list queries. Declare the boundary, drive with parameters, one line of code."&lt;/p&gt;




&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;

&lt;p&gt;If you've read this far and recognized every pain point I described — you should try this.&lt;/p&gt;

&lt;p&gt;No refactoring your project. No replacing your ORM. No changing your architecture. It's a completely non-invasive framework that coexists with MyBatis, JPA, and Spring Data JDBC.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;📖 &lt;a href="https://bs.zhxu.cn/en/" rel="noopener noreferrer"&gt;Full Documentation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🖥 &lt;a href="https://demo-bs.zhxu.cn/" rel="noopener noreferrer"&gt;Live Demo (zero setup)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;⭐ &lt;a href="https://github.com/troyzhxu/bean-searcher" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If this solves a real pain point for you, star the repo. Help more Java engineers trapped in if-else hell find their way out.&lt;/p&gt;

&lt;p&gt;After all — &lt;strong&gt;your life is worth more than writing if-else.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>api</category>
      <category>backend</category>
      <category>java</category>
      <category>sql</category>
    </item>
    <item>
      <title>REST-style GraphQL — one line of Java handles filtering + sorting + pagination + stats + CSV export. (Demo's in Chinese but you'll get the idea in 30 seconds) 👇
https://demo-bs.zhxu.cn/</title>
      <dc:creator>Troy</dc:creator>
      <pubDate>Sat, 25 Jul 2026 16:36:10 +0000</pubDate>
      <link>https://dev.to/troyzhxu/rest-style-graphql-one-line-of-java-handles-filtering-sorting-pagination-stats-csv-4nhi</link>
      <guid>https://dev.to/troyzhxu/rest-style-graphql-one-line-of-java-handles-filtering-sorting-pagination-stats-csv-4nhi</guid>
      <description>&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://demo-bs.zhxu.cn/" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo-bs.zhxu.cn%2Flogo.png" height="265" class="m-0" width="265"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://demo-bs.zhxu.cn/" rel="noopener noreferrer" class="c-link"&gt;
            Bean Searcher 在线演示 — 高级列表检索 | 一行代码实现复杂查询
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            一行代码实现分页、多条件组合过滤、任意字段排序、统计汇总。即刻在线体验！
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdemo-bs.zhxu.cn%2Flogo.png" width="265" height="265"&gt;
          demo-bs.zhxu.cn
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


</description>
      <category>api</category>
      <category>backend</category>
      <category>java</category>
      <category>programming</category>
    </item>
    <item>
      <title>Writing code like this improves efficiency by 100 times compared to directly using MyBatis</title>
      <dc:creator>Troy</dc:creator>
      <pubDate>Wed, 19 Jun 2024 15:34:03 +0000</pubDate>
      <link>https://dev.to/troyzhxu/writing-code-like-this-improves-efficiency-by-100-times-compared-to-directly-using-mybatis-49i2</link>
      <guid>https://dev.to/troyzhxu/writing-code-like-this-improves-efficiency-by-100-times-compared-to-directly-using-mybatis-49i2</guid>
      <description>&lt;p&gt;For a Java backend programmer, &lt;code&gt;MyBatis&lt;/code&gt;, &lt;code&gt;Hibernate&lt;/code&gt;, &lt;code&gt;Data Jdbc&lt;/code&gt;, and others are commonly used ORM frameworks. They are sometimes very useful, such as simple CRUD and excellent transaction support. But sometimes it can be very cumbersome to use, such as a common development requirement that we will talk about next. For this type of requirement, this article will provide a method that can improve development efficiency by &lt;strong&gt;at least 100 times&lt;/strong&gt; compared to directly using these ORMs (without exaggeration).&lt;/p&gt;

&lt;h2&gt;
  
  
  Firstly, the database has two tables
&lt;/h2&gt;

&lt;p&gt;User Table: (For simplicity, assume there are only 4 fields)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Figfws29nko5iaka1feru.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Figfws29nko5iaka1feru.png" alt="Image description" width="373" height="257"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Role table: (For simplicity, assume there are only 2 fields)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdjemgtg3uavg2b3fe7gy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdjemgtg3uavg2b3fe7gy.png" alt="Image description" width="375" height="163"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Next, we need to implement a user query function
&lt;/h2&gt;

&lt;p&gt;This query is a bit complex, and its requirements are as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Can be queried by the &lt;code&gt;username&lt;/code&gt; field, with the following requirements:

&lt;ul&gt;
&lt;li&gt;Can be accurately matched (equal to a certain value)&lt;/li&gt;
&lt;li&gt;Fully fuzzy matching (including given values)&lt;/li&gt;
&lt;li&gt;Post fuzzy query (starting with...)&lt;/li&gt;
&lt;li&gt;Pre fuzzy query (ending with...)&lt;/li&gt;
&lt;li&gt;Can you specify whether the above four matches can ignore case&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Can be queried by the &lt;code&gt;age&lt;/code&gt; field, with the following requirements:

&lt;ul&gt;
&lt;li&gt;Can be accurately matched (equal to a certain age)&lt;/li&gt;
&lt;li&gt;Can be greater than matching (greater than a certain value)&lt;/li&gt;
&lt;li&gt;Can be less than matching (less than a certain value)&lt;/li&gt;
&lt;li&gt;Interval matching (within a certain range of intervals)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Can be queried by &lt;code&gt;roleId&lt;/code&gt;, with the requirement of precise matching&lt;/li&gt;
&lt;li&gt;Can be queried by 'userId', requirement: same as 'age' field&lt;/li&gt;
&lt;li&gt;You can specify which columns to output only (for example, only query the &lt;code&gt;id&lt;/code&gt; and &lt;code&gt;username&lt;/code&gt; columns)&lt;/li&gt;
&lt;li&gt;Support pagination (after each query, the page should display the total number of users who meet the conditions)&lt;/li&gt;
&lt;li&gt;When querying, you can choose to sort by any field such as &lt;code&gt;id&lt;/code&gt;, &lt;code&gt;username&lt;/code&gt;, &lt;code&gt;age&lt;/code&gt;, etc&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How should the backend interface be written?
&lt;/h2&gt;

&lt;p&gt;Imagine, for this type of query, if the code in the backend interface is written directly using &lt;code&gt;MyBatis&lt;/code&gt;, &lt;code&gt;Hibernate&lt;/code&gt; or &lt;code&gt;Data Jdbc&lt;/code&gt;, can it be completed within &lt;strong&gt;100 lines of code&lt;/strong&gt; ?&lt;/p&gt;

&lt;p&gt;Anyway, I don't have the confidence. Forget it, I'll just be honest. How can I handle this kind of requirement &lt;strong&gt;with just one line of code&lt;/strong&gt; on the backend? (Interested students can try MyBatis and compare it in the end)&lt;/p&gt;

&lt;h2&gt;
  
  
  Only one line of code is used to implement the above requirements
&lt;/h2&gt;

&lt;p&gt;First of all, the key figure has appeared: &lt;strong&gt;Bean Searcher&lt;/strong&gt;, which is a &lt;strong&gt;read-only ORM&lt;/strong&gt; that focuses on &lt;strong&gt;advanced queries&lt;/strong&gt;. For this type of list retrieval, whether it is simple or complex, it can be done in one line of code! And it is also very lightweight and has no third-party dependencies (can be used in the same project as any other ORM).&lt;/p&gt;

&lt;p&gt;Assuming that the framework we are using in our project is Spring Boot (Of course, Bean Searcher does not have any special requirements for web frameworks, but it is more convenient to use in Spring Boot).&lt;/p&gt;

&lt;h3&gt;
  
  
  Add Dependency
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Maven:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;cn.zhxu&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;bean-searcher-boot-starter&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;4.3.0&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Gradle:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;implementation&lt;/span&gt; &lt;span class="s1"&gt;'cn.zhxu:bean-searcher-boot-starter:4.3.0'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Then write an entity class to carry the results of the query
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@SearchBean&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tables&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"user u, role r"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;where&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"u.role_id = r.id"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;autoMapTo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"u"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; 
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;        &lt;span class="c1"&gt;// User ID (u.id)&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;    &lt;span class="c1"&gt;// User Name (u.name) &lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;        &lt;span class="c1"&gt;// Age (u.age) &lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;roleId&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;     &lt;span class="c1"&gt;// Role ID (u.role_id) &lt;/span&gt;
    &lt;span class="nd"&gt;@DbField&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"r.name"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;      &lt;span class="c1"&gt;// Indicates that this attribute comes from the name field of the role table&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;    &lt;span class="c1"&gt;// Role Name (r.name) &lt;/span&gt;
    &lt;span class="c1"&gt;// Getter and Setter ...&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note: This entity class is mapped to two tables and can be directly returned to the front-end&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Then we can write the user query interface
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@RestController&lt;/span&gt;
&lt;span class="nd"&gt;@RequestMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/user"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserController&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Autowired&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;MapSearcher&lt;/span&gt; &lt;span class="n"&gt;mapSearcher&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// injection searcher (provided by bean-searcher-boot-starter)&lt;/span&gt;

    &lt;span class="nd"&gt;@GetMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/index"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;SearchResult&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HttpServletRequest&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Here we only write one line of code&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;mapSearcher&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;search&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;MapUtils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;flat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getParameterMap&lt;/span&gt;&lt;span class="o"&gt;()));&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;The &lt;code&gt;MapUtils&lt;/code&gt; in the above code is a tool provided by Bean Searcher, while &lt;code&gt;MapUtils.flat(request. getParameterMap())&lt;/code&gt; is only used to collect the request parameters passed from the front-end, and the rest is handed over to the &lt;code&gt;MapSearcher&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Is that all? Let's test this interface and see the effect
&lt;/h2&gt;

&lt;h3&gt;
  
  
  (1) No parameter request
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;GET /user/index&lt;/li&gt;
&lt;li&gt;Return result:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dataList"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;User&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;list&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;returns&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;page&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;by&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;default&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;with&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;default&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;page&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;size&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;(configurable)&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Jack"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"age"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"roleId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"role"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"VIP"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Tom"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"age"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"roleId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"role"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"VIP"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"totalCount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Total&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;number&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;users&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  (2) Paging request (page | size)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;GET /user/index? page=2 &amp;amp; size=10&lt;/li&gt;
&lt;li&gt;Return result: The structure is the same as &lt;strong&gt;(1)&lt;/strong&gt; (only 10 items per page, with page 2)&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;The parameter names &lt;code&gt;size&lt;/code&gt; and &lt;code&gt;page&lt;/code&gt; can be customized, with &lt;code&gt;page&lt;/code&gt; starting from &lt;code&gt;0&lt;/code&gt; by default. They can also be customized and can be used in combination with other parameters.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  (3) Data sorting (sort | order)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;GET /user/index? sort=age &amp;amp; order=desc&lt;/li&gt;
&lt;li&gt;Return result: The structure is the same as &lt;strong&gt;(1)&lt;/strong&gt; (except that the dataList is output in descending order of the age field)&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;The parameter names &lt;code&gt;sort&lt;/code&gt; and &lt;code&gt;order&lt;/code&gt; are customizable and can be used in combination with other parameters.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  (4) Specify (exclude) fields (onlySelect | selectExclude)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;GET /user/index? onlySelect=id,name,role&lt;/li&gt;
&lt;li&gt;GET /user/index? selectExclude=age,roleId&lt;/li&gt;
&lt;li&gt;Return result: (The list only contains three fields: &lt;code&gt;id&lt;/code&gt;, &lt;code&gt;name&lt;/code&gt;, and &lt;code&gt;role&lt;/code&gt;)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dataList"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;User&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;list&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;returns&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;page&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;by&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;default&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;(only&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;containing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;role&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;fields)&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Jack"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"role"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"VIP"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Tom"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"role"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"VIP"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"totalCount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Total&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;number&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;users&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;The parameter names &lt;code&gt;onlySelect&lt;/code&gt; and &lt;code&gt;selectExclude&lt;/code&gt; are customizable and can be used in combination with other parameters.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  (5) Field filtering (op = eq)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;GET /user/index? age=20&lt;/li&gt;
&lt;li&gt;GET /user/index? age=20 &amp;amp; age-op=eq&lt;/li&gt;
&lt;li&gt;GET /user/index? age-eq=20 &lt;code&gt;Simplified writing, reference: https://bs.zhxu.cn/guide/advance/filter.html#suffixopparamfilter&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Return result: The structure is the same as &lt;strong&gt;(1)&lt;/strong&gt; (but only returns data with age=20)&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;The parameter &lt;code&gt;age-op=eq&lt;/code&gt; represents the &lt;strong&gt;field operator&lt;/strong&gt; of &lt;code&gt;age&lt;/code&gt;, which is &lt;code&gt;eq&lt;/code&gt;(abbreviation for &lt;code&gt;Equal&lt;/code&gt;), indicating that the relationship between parameter &lt;code&gt;age&lt;/code&gt; and parameter value &lt;code&gt;20&lt;/code&gt; is &lt;code&gt;Equal&lt;/code&gt;. Since &lt;code&gt;Equal&lt;/code&gt; is a default relationship, &lt;code&gt;age-op=eq&lt;/code&gt; can also be omitted.&lt;br&gt;
The suffix &lt;code&gt;-op&lt;/code&gt; for the parameter name &lt;code&gt;age-op&lt;/code&gt; is customizable and can be used in combination with other field parameters and the parameters listed above (pagination, sorting, specified fields). The same applies to the field parameters listed below and will not be repeated.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  (6) Field filtering (op = ne)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;GET /user/index? age=20 &amp;amp; age-op=ne&lt;/li&gt;
&lt;li&gt;GET /user/index? age-ne=20 &lt;code&gt;Simplified version, reference: https://bs.zhxu.cn/guide/advance/filter.html#suffixopparamfilter&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Return result: The structure is the same as &lt;strong&gt;(1)&lt;/strong&gt; (but only returns data with age != 20, where &lt;code&gt;ne&lt;/code&gt; is an abbreviation for &lt;code&gt;NotEqual&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  (7) Field filtering (op = ge)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;GET /user/index? age=20 &amp;amp; age-op=ge&lt;/li&gt;
&lt;li&gt;GET /user/index? age-ge=20 &lt;code&gt;Simplified version, reference: https://bs.zhxu.cn/guide/advance/filter.html#suffixopparamfilter&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Return result: The structure is the same as &lt;strong&gt;(1)&lt;/strong&gt; (but only returns data with age &amp;gt;= 20, where &lt;code&gt;ge&lt;/code&gt; is the abbreviation of &lt;code&gt;GreateEqual&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  (8) Field filtering (op = le)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;GET /user/index? age=20 &amp;amp; age-op=le&lt;/li&gt;
&lt;li&gt;GET /user/index? age-le=20 &lt;code&gt;Simplified version, reference: https://bs.zhxu.cn/guide/advance/filter.html#suffixopparamfilter&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Return result: The structure is the same as &lt;strong&gt;(1)&lt;/strong&gt; (but only returns data with age &amp;lt;= 20, where &lt;code&gt;le&lt;/code&gt; is the abbreviation of &lt;code&gt;LessEqual&lt;/code&gt;) &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  (9) Field filtering (op = gt)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;GET /user/index? age=20 &amp;amp; age-op=gt&lt;/li&gt;
&lt;li&gt;GET /user/index? age-gt=20 &lt;code&gt;Simplified version, reference: https://bs.zhxu.cn/guide/advance/filter.html#suffixopparamfilter&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Return result: The structure is the same as &lt;strong&gt;(1)&lt;/strong&gt; (but only returns data with age &amp;gt; 20, where &lt;code&gt;gt&lt;/code&gt; is the abbreviation of&lt;code&gt;GreateThan&lt;/code&gt;) &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  (10) Field filtering (op = lt)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;GET /user/index? age=20 &amp;amp; age-op=lt&lt;/li&gt;
&lt;li&gt;GET /user/index? age-lt=20 &lt;code&gt;Simplified version, reference: https://bs.zhxu.cn/guide/advance/filter.html#suffixopparamfilter&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Return result: The structure is the same as &lt;strong&gt;(1)&lt;/strong&gt; (but only returns data with age &amp;lt; 20, where &lt;code&gt;lt&lt;/code&gt; is the abbreviation of&lt;code&gt;LessThan&lt;/code&gt;) &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  (11) Field filtering (op = bt)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;GET /user/index? age-0=20 &amp;amp; age-1=30 &amp;amp; age-op=bt&lt;/li&gt;
&lt;li&gt;GET /user/index? age=[20,30] &amp;amp; age-op=bt (&lt;strong&gt;Simplified version&lt;/strong&gt;，[20,30] requires UrlEncode, refer to the following text) &lt;/li&gt;
&lt;li&gt;GET /user/index? age-bt=[20,30] &lt;code&gt;Simplify again, refer to：https://bs.zhxu.cn/guide/advance/filter.html#suffixopparamfilter&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Return result: The structure is the same as &lt;strong&gt;(1)&lt;/strong&gt; (but only returns data with 20 &amp;lt;= age &amp;lt;= 30, where &lt;code&gt;bt&lt;/code&gt; is the abbreviation of &lt;code&gt;Between&lt;/code&gt;) &lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;The parameter &lt;code&gt;age-0 = 20&lt;/code&gt; indicates that the 0th parameter value of &lt;code&gt;age&lt;/code&gt; is &lt;code&gt;20&lt;/code&gt;. The above-mentioned &lt;code&gt;age=20&lt;/code&gt; is actually a shortened form of &lt;code&gt;age-0=20&lt;/code&gt;. Additionally, the hyphen &lt;code&gt;-&lt;/code&gt; in the parameter names &lt;code&gt;age-0&lt;/code&gt; and &lt;code&gt;age-1&lt;/code&gt; can be customized.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  (12) Field filtering (op = il)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;GET /user/index? age-0=20 &amp;amp; age-1=30 &amp;amp; age-2=40 &amp;amp; age-op=il&lt;/li&gt;
&lt;li&gt;GET /user/index? age=[20,30,40] &amp;amp; age-op=il (&lt;strong&gt;Simplified version&lt;/strong&gt;，[20,30,40] requires UrlEncode, refer to the following text) &lt;/li&gt;
&lt;li&gt;GET /user/index? age-il=[20,30,40] &lt;code&gt;Simplify again, refer to：https://bs.zhxu.cn/guide/advance/filter.html#suffixopparamfilter&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Return result: The structure is the same as &lt;strong&gt;(1)&lt;/strong&gt; (but only returns data with age in (20, 30, 40), where &lt;code&gt;il&lt;/code&gt; is the abbreviation of &lt;code&gt;InList&lt;/code&gt;) &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  (13) Field filtering (op = ct)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;GET /user/index? name=Jack &amp;amp; name-op=ct&lt;/li&gt;
&lt;li&gt;GET /user/index? name-ct=Jack &lt;code&gt;Simplified version, reference: https://bs.zhxu.cn/guide/advance/filter.html#suffixopparamfilter&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Return result: The structure is the same as &lt;strong&gt;(1)&lt;/strong&gt; (but only returns data with name contains Jack, where &lt;code&gt;ct&lt;/code&gt; is the abbreviation of &lt;code&gt;Contain&lt;/code&gt;) &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  (14) Field filtering (op = sw)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;GET /user/index? name=Jack &amp;amp; name-op=sw&lt;/li&gt;
&lt;li&gt;GET /user/index? name-sw=Jack &lt;code&gt;Simplified version, reference: https://bs.zhxu.cn/guide/advance/filter.html#suffixopparamfilter&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Return result: The structure is the same as &lt;strong&gt;(1)&lt;/strong&gt; (but only returns data with name staring with 'Jack', where &lt;code&gt;sw&lt;/code&gt; is the abbreviation of &lt;code&gt;StartWith&lt;/code&gt;) &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  (15) Field filtering (op = ew)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;GET /user/index? name=Jack &amp;amp; name-op=ew&lt;/li&gt;
&lt;li&gt;GET /user/index? name-ew=Jack &lt;code&gt;Simplified version, reference: https://bs.zhxu.cn/guide/advance/filter.html#suffixopparamfilter&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Return result: The structure is the same as &lt;strong&gt;(1)&lt;/strong&gt; (but only returns data with name ending with 'Jack', where &lt;code&gt;ew&lt;/code&gt; is the abbreviation of &lt;code&gt;EndWith&lt;/code&gt;) &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  (16)  Ignoring case (ic = true)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;GET /user/index? name=Jack &amp;amp; name-ic=true&lt;/li&gt;
&lt;li&gt;Return result: The structure is the same as &lt;strong&gt;(1)&lt;/strong&gt; (but only returns data with name equal with &lt;code&gt;Jack&lt;/code&gt;(ignore case), where &lt;code&gt;ic&lt;/code&gt; is the abbreviation of &lt;code&gt;IgnoreCase&lt;/code&gt;) &lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;The suffix &lt;code&gt;-ic&lt;/code&gt; in the parameter name &lt;code&gt;name-ic&lt;/code&gt; is customizable and can be used in combination with other parameters. For example, when retrieving a name equal to &lt;code&gt;Jack&lt;/code&gt;, case is ignored, but it is also applicable when retrieving a name starting or ending with &lt;code&gt;Jack&lt;/code&gt;, case is ignored.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;More search methods are also supported, and we will not provide examples here. To learn more, please refer: &lt;a href="https://bs.zhxu.cn/guide/param/field.html#%E5%AD%97%E6%AE%B5%E8%BF%90%E7%AE%97%E7%AC%A6"&gt;https://bs.zhxu.cn/guide/param/field.html#%E5%AD%97%E6%AE%B5%E8%BF%90%E7%AE%97%E7%AC%A6&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Of course, all of the above conditions can be combined.
&lt;/h3&gt;

&lt;p&gt;Such as: Query &lt;code&gt;name&lt;/code&gt; starting with 'Jack' (ignoring case), &lt;code&gt;roleId=1&lt;/code&gt;, results sorted by &lt;code&gt;id&lt;/code&gt; field, loading 10 entries per page, query page 2:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GET /user/index? name=Jack &amp;amp; name-op=sw &amp;amp; name-ic=true &amp;amp; roleId=1 &amp;amp; sort=id &amp;amp; size=10 &amp;amp; page=2&lt;/li&gt;
&lt;li&gt;Return result: The structure is the same as &lt;strong&gt;(1)&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;In fact, Bean Searcher also supports more search methods (even customizable), so we won't list them all here.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;OK， After seeing the effect, we have only written one line of code in the &lt;code&gt;GET /user/index&lt;/code&gt; interface, which can support so many retrieval methods. Do you think that now &lt;strong&gt;you can write a single line of code&lt;/strong&gt; can be equivalent to &lt;strong&gt;someone else's 100 lines&lt;/strong&gt;?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flwm19dm3ycuyzxdvytr4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flwm19dm3ycuyzxdvytr4.png" alt="Image description" width="800" height="302"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Bean Searcher
&lt;/h2&gt;

&lt;p&gt;In this example, we only used one retrieval method from the &lt;code&gt;MapSearcher&lt;/code&gt; retriever provided by Bean Searcher, which actually has many other retrieval methods.&lt;/p&gt;

&lt;h3&gt;
  
  
  Retrieval methods
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;searchCount(Class&amp;lt;T&amp;gt; beanClass, Map&amp;lt;String, Object&amp;gt; params)&lt;/code&gt; Query the &lt;strong&gt;total number&lt;/strong&gt; of data under specified conditions&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;searchSum(Class&amp;lt;T&amp;gt; beanClass, Map&amp;lt;String, Object&amp;gt; params, String field)&lt;/code&gt; Query the &lt;strong&gt;statistical value&lt;/strong&gt; of &lt;strong&gt;a certain field&lt;/strong&gt; under specified conditions&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;searchSum(Class&amp;lt;T&amp;gt; beanClass, Map&amp;lt;String, Object&amp;gt; params, String[] fields)&lt;/code&gt; Query the &lt;strong&gt;statistical values&lt;/strong&gt; of &lt;strong&gt;multiple fields&lt;/strong&gt; under specified conditions&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;search(Class&amp;lt;T&amp;gt; beanClass, Map&amp;lt;String, Object&amp;gt; params)&lt;/code&gt; &lt;strong&gt;Paging&lt;/strong&gt; query &lt;strong&gt;List&lt;/strong&gt; data and &lt;strong&gt;Total number of entries&lt;/strong&gt; under specified conditions&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;search(Class&amp;lt;T&amp;gt; beanClass, Map&amp;lt;String, Object&amp;gt; params, String[] summaryFields)&lt;/code&gt; &lt;strong&gt;Same as above&lt;/strong&gt; + multi field &lt;strong&gt;statistics&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;searchFirst(Class&amp;lt;T&amp;gt; beanClass, Map&amp;lt;String, Object&amp;gt; params)&lt;/code&gt; Query the &lt;strong&gt;first&lt;/strong&gt; data under specified conditions&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;searchList(Class&amp;lt;T&amp;gt; beanClass, Map&amp;lt;String, Object&amp;gt; params)&lt;/code&gt; &lt;strong&gt;Paging&lt;/strong&gt; Query &lt;strong&gt;List&lt;/strong&gt; data under specified conditions&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;searchAll(Class&amp;lt;T&amp;gt; beanClass, Map&amp;lt;String, Object&amp;gt; params)&lt;/code&gt; Query a list of &lt;strong&gt;all data&lt;/strong&gt; under specified conditions&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  MapSearcher and BeanSearcher
&lt;/h3&gt;

&lt;p&gt;In addition, Bean Searcher provides not only a 'MapSearcher' retriever, but also a 'BeanSearcher' retriever, which also has all the methods of 'MapSearcher'. However, the single data it returns is not a 'Map', but a &lt;strong&gt;generic&lt;/strong&gt; object.&lt;/p&gt;

&lt;h3&gt;
  
  
  Parameter construction tool
&lt;/h3&gt;

&lt;p&gt;Additionally, if you are using Bean Searcher in a Service, using parameters of type &lt;code&gt;Map&amp;lt;String, Object&amp;gt;&lt;/code&gt; directly may not be elegant. Therefore, Bean Searcher specifically provides a parameter construction tool.&lt;/p&gt;

&lt;p&gt;For example, if the query &lt;code&gt;name&lt;/code&gt; starts with 'Jack' (ignoring case) and &lt;code&gt;roleId=1&lt;/code&gt;, and the result is sorted by the &lt;code&gt;id&lt;/code&gt; field, load &lt;code&gt;10&lt;/code&gt; entries per page, load page &lt;code&gt;2&lt;/code&gt;, and use a parameter builder, the code can be written as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MapUtils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;field&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;User:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;getName&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Jack"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;op&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Operator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;StartWith&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;ic&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;field&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;User:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;getRoleId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;orderBy&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;User:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;getId&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;asc&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;page&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;beanSearcher&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;searchList&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;The &lt;code&gt;BeanSearcher&lt;/code&gt; retriever and its' &lt;code&gt;searchList (Class&amp;lt;T&amp;gt; beanClass, Map&amp;lt;String, Object&amp;gt; params)&lt;/code&gt; method are used here.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Operator constraints
&lt;/h3&gt;

&lt;p&gt;As we saw earlier, Bean Searcher directly supports many retrieval methods for each field in the entity class.&lt;/p&gt;

&lt;p&gt;But a classmate: Oh my! There are too many search methods, I don't need so many at all. &lt;strong&gt;My data volume is billions, and the fuzzy query method before the username field cannot utilize the index. What if my database crashes&lt;/strong&gt;?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Easy to handle&lt;/strong&gt;, Bean Searcher supports operator constraints, and the &lt;code&gt;name&lt;/code&gt; field of the entity class only needs to be annotated:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@SearchBean&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tables&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"user u, role r"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;where&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"u.role_id = r.id"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;autoMapTo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"u"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; 
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@DbField&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;onlyOn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;Equal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;StartWith&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;})&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By using the &lt;code&gt;onlyOn&lt;/code&gt; attribute of &lt;code&gt;@DbField&lt;/code&gt;, it is specified that the &lt;code&gt;name&lt;/code&gt; field can only be used for &lt;code&gt;Equal&lt;/code&gt; and &lt;code&gt;StartWith&lt;/code&gt; operators, and other operators will be ignored directly.&lt;/p&gt;

&lt;p&gt;The above code restricts &lt;code&gt;name&lt;/code&gt; to only two operators. If it is stricter and only allows precise matching, there are actually two ways to write it.&lt;/p&gt;

&lt;h5&gt;
  
  
  (1) use operator constraints:
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@SearchBean&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tables&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"user u, role r"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;where&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"u.role_id = r.id"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;autoMapTo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"u"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; 
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@DbField&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;onlyOn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Equal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  (2) Overwrite operator parameters in the method of Controller:
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@GetMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/index"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;SearchResult&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HttpServletRequest&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MapUtils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;flatBuilder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getParameterMap&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;field&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;User:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;getName&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;op&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Operator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Equal&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;// Overwrite the operator of the name field directly to Equal&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;mapSearcher&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;search&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Conditional constraints
&lt;/h3&gt;

&lt;p&gt;The student said also: Oh my! &lt;strong&gt;My data volume is still very large, and the age field has no index. I don't want it to participate in the where condition, otherwise it is likely to cause slow SQLs&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don't worry&lt;/strong&gt;, Bean Searcher also supports conditional constraints, making this field directly unavailable as a condition:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@SearchBean&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tables&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"user u, role r"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;where&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"u.role_id = r.id"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;autoMapTo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"u"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; 
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@DbField&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conditional&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By using the &lt;code&gt;conditional&lt;/code&gt; attribute of &lt;code&gt;@DbField&lt;/code&gt;, the &lt;code&gt;age&lt;/code&gt; field is directly not allowed to participate in the condition. No matter how the frontend passes the parameter, the Bean Searcher always ignores it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Parameter filter
&lt;/h3&gt;

&lt;p&gt;The student still said: Oh my! Oh my...&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don't be afraid&lt;/strong&gt; Bean Searcher also supports configuring global parameter filters and can customize any parameter filtering rules. In the SpringBoot project, only one bean needs to be declared:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Bean&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;ParamFilter&lt;/span&gt; &lt;span class="nf"&gt;myParamFilter&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ParamFilter&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nd"&gt;@Override&lt;/span&gt;
        &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;doFilter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;BeanMeta&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;beanMeta&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;paraMap&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// beanMeta is the meta information of the entity class being retrieved, and paraMap is the current retrieval parameters&lt;/span&gt;
            &lt;span class="c1"&gt;// TODO: Here you can write some custom parameter filtering rules&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;paraMap&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;      &lt;span class="c1"&gt;// Returns the filtered search parameters&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;};&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Another classmate asked
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Why are the parameters so strange? With so many parameters, is there any grudge against the front-end?
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Whether the parameter name is strange or not depends on personal preference. If you don't like the hyphen &lt;code&gt;-&lt;/code&gt;, the suffix &lt;code&gt;op&lt;/code&gt;, or &lt;code&gt;ic&lt;/code&gt;, you can completely customize it. Please refer to this document: &lt;a href="https://bs.zhxu.cn/guide/param/field.html"&gt;https://bs.zhxu.cn/guide/param/field.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The number of parameters is actually related to the complexity of the product requirements. If the requirements are very simple, then many parameters do not need to be sent from the front-end, and the back-end can simply plug them in. For example, if &lt;code&gt;name&lt;/code&gt; only requires post fuzzy matching and &lt;code&gt;age&lt;/code&gt; only requires interval matching, then it can:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@GetMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/index"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;SearchResult&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HttpServletRequest&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MapUtils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;flatBuilder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getParameterMap&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;field&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;User:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;getName&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;op&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Operator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;StartWith&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;field&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;User:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;getAge&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;op&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Operator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Between&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;mapSearcher&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;search&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way, the front-end does not need to sent the &lt;code&gt;name-op&lt;/code&gt; and &lt;code&gt;age-op&lt;/code&gt; parameters.&lt;/p&gt;

&lt;p&gt;There is actually a simpler method, which is the &lt;strong&gt;operator constraint&lt;/strong&gt; (when the constraint exists, the operator defaults to the first value specified in the &lt;code&gt;onlyOn&lt;/code&gt; attribute, which can be omitted from the frontend):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@SearchBean&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tables&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"user u, role r"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;where&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"u.role_id = r.id"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;autoMapTo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"u"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; 
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@DbField&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;onlyOn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Operator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;StartWith&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nd"&gt;@DbField&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;onlyOn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Operator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Between&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;For multi valued parameter passing with &lt;strong&gt;op=bt/il&lt;/strong&gt;, parameters can indeed be simplified, for example: &lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Simplify &lt;code&gt;age-0=20 &amp;amp; age-1=30 &amp;amp; age-op=bt&lt;/code&gt; to &lt;code&gt;age=[20,30] &amp;amp; age-op=bt&lt;/code&gt; and further simplify it to &lt;code&gt;age-bt=[20,30]&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;Simplify &lt;code&gt;age-0=20 &amp;amp; age-1=30 &amp;amp; age-2=40 &amp;amp; age-op=il&lt;/code&gt; to &lt;code&gt;age=[20,30,40] &amp;amp; age-op=il&lt;/code&gt; and further simplify it to &lt;code&gt;age-il=[20,30,40]&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Simplification method: Just enable one configuration, please refer here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bs.zhxu.cn/guide/advance/filter.html#jsonarrayparamfilter"&gt;https://bs.zhxu.cn/guide/advance/filter.html#jsonarrayparamfilter&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The input parameter is a request, but the Swagger document is not easy to render
&lt;/h3&gt;

&lt;p&gt;In fact, the retriever of Bean Searcher only requires a parameter of type &lt;code&gt;Map&amp;lt;String, Object&amp;gt;&lt;/code&gt;, and how this parameter is obtained is not directly related to Bean Searcher. The reason why I use &lt;code&gt;request&lt;/code&gt; is because it makes the code look concise. If you like to declare parameters, you can write the code as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@GetMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/index"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;SearchResult&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Integer&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Integer&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; 
            &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;sort&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Integer&lt;/span&gt; &lt;span class="n"&gt;roleId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
            &lt;span class="nd"&gt;@RequestParam&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"name-op"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;required&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name_op&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
            &lt;span class="nd"&gt;@RequestParam&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"name-ic"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;required&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nc"&gt;Boolean&lt;/span&gt; &lt;span class="n"&gt;name_ic&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
            &lt;span class="nd"&gt;@RequestParam&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"age-0"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;required&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nc"&gt;Integer&lt;/span&gt; &lt;span class="n"&gt;age_0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
            &lt;span class="nd"&gt;@RequestParam&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"age-1"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;required&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nc"&gt;Integer&lt;/span&gt; &lt;span class="n"&gt;age_1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
            &lt;span class="nd"&gt;@RequestParam&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"age-op"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;required&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;age_op&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MapUtils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;field&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;Employee:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;getName&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;op&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name_op&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;ic&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name_ic&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;field&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;Employee:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;getAge&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;age_0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;age_1&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;op&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;age_op&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;field&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;Employee:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;getRoleId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;roleId&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;orderBy&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sort&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;page&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;mapSearcher&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;search&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The relationship between field parameters is "and", what about "or"? And any combination of "or" and "and"?
&lt;/h3&gt;

&lt;p&gt;As for "or", although there are not many usage scenarios, Bean Searcher still supports it (and it is very &lt;strong&gt;convenient&lt;/strong&gt; and &lt;strong&gt;powerful&lt;/strong&gt;). For more details, please refer: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bs.zhxu.cn/guide/param/group.html"&gt;https://bs.zhxu.cn/guide/param/group.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I won't repeat it here.&lt;/p&gt;

&lt;h3&gt;
  
  
  Are the values of parameters such as &lt;code&gt;sort&lt;/code&gt; and &lt;code&gt;onlySelect&lt;/code&gt; in the previous text the field names of the data table, and is there a risk of SQL injection?
&lt;/h3&gt;

&lt;p&gt;You can completely be at ease on it. SQL injection, such a low-level error, was already avoided at the beginning of framework design. The values of parameters such as &lt;code&gt;sort&lt;/code&gt; and &lt;code&gt;onlySelect&lt;/code&gt; are all attribute names of the &lt;strong&gt;entity class&lt;/strong&gt; (rather than fields in the data table). When the user passes a value that is not a certain attribute name, the framework will automatically ignore them, and there is no injection problem.&lt;/p&gt;

&lt;p&gt;Not only that, Bean Searcher also comes with &lt;strong&gt;pagination protection&lt;/strong&gt; function to ensure the security of your service, which can effectively block malicious large page requests from clients.&lt;/p&gt;

&lt;h3&gt;
  
  
  Has development efficiency really increased by 100 times?
&lt;/h3&gt;

&lt;p&gt;From this example, it can be seen that the degree of efficiency improvement depends on the complexity of the retrieval requirements. &lt;strong&gt;The more complex the demand, the higher the efficiency improvement&lt;/strong&gt;. Conversely, the lower the efficiency improvement. If the demand is super complex, it is possible to increase it by &lt;strong&gt;1000&lt;/strong&gt; times.&lt;br&gt;
But even if we don't have such complex requirements in our daily development, and the development efficiency only improves by &lt;strong&gt;3 to 5&lt;/strong&gt; times, is that still very impressive?&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This article introduces the powerful capabilities of &lt;strong&gt;Bean Searcher&lt;/strong&gt; in the field of complex list retrieval. The reason why it can greatly improve the development efficiency of such requirements is fundamentally attributed to its &lt;strong&gt;original dynamic field operator&lt;/strong&gt; and &lt;strong&gt;multi table mapping mechanism&lt;/strong&gt;, which is not available in traditional ORM frameworks. However, due to space limitations, its characteristics cannot be fully described in this article, for example, it also:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Support &lt;strong&gt;aggregation queries&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Support &lt;strong&gt;Select|Where|From sub queries&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Support &lt;strong&gt;entity class embedding parameters&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Support &lt;strong&gt;parameter grouping and logic optimization&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Support &lt;strong&gt;Field Converter&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Support &lt;strong&gt;Sql interceptor&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Support &lt;strong&gt;Database Dialect extension&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Support &lt;strong&gt;multiple datasources&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Support &lt;strong&gt;custom operators&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Support &lt;strong&gt;custom annotations&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;And so on..&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To learn more, pleast star it on &lt;strong&gt;&lt;a href="https://github.com/troyzhxu/bean-searcher"&gt;Github&lt;/a&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;a href="https://gitee.com/troyzhxu/bean-searcher"&gt;Gitee&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Detailed documentation: &lt;a href="https://bs.zhxu.cn"&gt;https://bs.zhxu.cn&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>orm</category>
      <category>beansearcher</category>
    </item>
  </channel>
</rss>
