current position:Home>Custom orm of 30 classes handwritten spring core principles (Part 1) (6)

Custom orm of 30 classes handwritten spring core principles (Part 1) (6)

2022-01-27 01:17:05 Tom bomb architecture

This article is excerpted from 《Spring 5 The core principle 》

1 Overview of implementation ideas

1.1 from ResultSet Speaking of

Speaking of ResultSet, Yes Java Development experience “ buddy ” Nature is the most familiar , But I believe for most people, it's also “ The most familiar stranger ”. from ResultSet Value taking operation, everyone will , such as :


private static List<Member> select(String sql) {
    
    List<Member> result = new ArrayList<>();
    Connection con = null;
    PreparedStatement pstm = null;
    ResultSet rs = null;
    try {
    
        //1.  Load driver class 
        Class.forName("com.mysql.jdbc.Driver");
        //2.  Establishing a connection 
        con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/gp-vip-spring-db-demo", "root","123456");
        //3.  Create a statement set 
        pstm =  con.prepareStatement(sql);
        //4.  Execution statement set 
        rs = pstm.executeQuery();
        while (rs.next()){
    
            Member instance = new Member();
            instance.setId(rs.getLong("id"));
            instance.setName(rs.getString("name"));
            instance.setAge(rs.getInt("age"));
            instance.setAddr(rs.getString("addr"));
            result.add(instance);
        }
        //5.  Get the result set 
    }catch (Exception e){
    
        e.printStackTrace();
    }
    //6.  Close result set 、 Close statement set 、 Close the connection 
    finally {
    
        try {
    
            rs.close();
            pstm.close();
            con.close();
        }catch (Exception e){
    
            e.printStackTrace();
        }
    }
    return result;
}

The above is our routine operation before using the framework . With the increase of business and development , In the data persistence layer, such repeated code occurs very frequently . therefore , We thought of separating non functional code from business code . The first thing we think about is ResultSet Code logic separation of encapsulated data , Add one more mapperRow() Method , Specialized in the encapsulation of results , The code is as follows :


private static List<Member> select(String sql) {
    
    List<Member> result = new ArrayList<>();
    Connection con = null;
    PreparedStatement pstm = null;
    ResultSet rs = null;
    try {
    
        //1.  Load driver class 
        Class.forName("com.mysql.jdbc.Driver");
        //2.  Establishing a connection 
        con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/gp-vip-spring-db-demo", "root","123456");
        //3.  Create a statement set 
        pstm =  con.prepareStatement(sql);
        //4.  Execution statement set 
        rs = pstm.executeQuery();
        while (rs.next()){
    
            Member instance = mapperRow(rs,rs.getRow());
            result.add(instance);
        }
        //5.  Get the result set 
    }catch (Exception e){
    
        e.printStackTrace();
    }
    //6.  Close result set 、 Close statement set 、 Close the connection 
    finally {
    
        try {
    
            rs.close();
            pstm.close();
            con.close();
        }catch (Exception e){
    
            e.printStackTrace();
        }
    }
    return result;
}

private static Member mapperRow(ResultSet rs, int i) throws Exception {
    
    Member instance = new Member();
    instance.setId(rs.getLong("id"));
    instance.setName(rs.getString("name"));
    instance.setAge(rs.getInt("age"));
    instance.setAddr(rs.getString("addr"));
    return instance;
}

But in a real business scenario , Such code logic repetition rate is too high , The above transformation can only be applied Member class , Another entity class has to be re encapsulated , A smart programmer certainly won't write one for every entity class through pure manual labor mapperRow() Method , You will think of a code reuse scheme . We might as well do such a transformation .
First create Member class :


package com.gupaoedu.vip.orm.demo.entity;

import lombok.Data;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import java.io.Serializable;

@Entity
@Table(name="t_member")
@Data
public class Member implements Serializable {
    
    @Id private Long id;
    private String name;
    private String addr;
    private Integer age;

    @Override
    public String toString() {
    
        return "Member{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", addr='" + addr + '\'' +
                ", age=" + age +
                '}';
    }
}

Optimize JDBC operation :


public static void main(String[] args) {
    
    Member condition = new Member();
    condition.setName("Tom");
    condition.setAge(19);
    List<?> result =  select(condition);
    System.out.println(Arrays.toString(result.toArray()));
}

private static List<?> select(Object condition) {
    

    List<Object> result = new ArrayList<>();

    Class<?> entityClass = condition.getClass();

    Connection con = null;
    PreparedStatement pstm = null;
    ResultSet rs = null;
    try {
    
        //1.  Load driver class 
        Class.forName("com.mysql.jdbc.Driver");
        //2.  Establishing a connection 
        con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/gp-vip-spring-db-demo? characterEncoding=UTF-8&rewriteBatchedStatements=true","root","123456");

        // Find the attribute name according to the class name 
        Map<String,String> columnMapper = new HashMap<String,String>();
        // Find the field name according to the attribute name 
        Map<String,String> fieldMapper = new HashMap<String,String>();
        Field[] fields =  entityClass.getDeclaredFields();
        for (Field field : fields) {
    
            field.setAccessible(true);
            String fieldName = field.getName();
            if(field.isAnnotationPresent(Column.class)){
    
                Column column = field.getAnnotation(Column.class);
                String columnName = column.name();
                columnMapper.put(columnName,fieldName);
                fieldMapper.put(fieldName,columnName);
            }else {
    
                // The default is the field name 、 Consistent property names 
                columnMapper.put(fieldName, fieldName);
                fieldMapper.put(fieldName,fieldName);
            }
        }

        //3.  Create a statement set 
        Table table = entityClass.getAnnotation(Table.class);
        String sql = "select * from " + table.name();

        StringBuffer where = new StringBuffer(" where 1=1 ");
        for (Field field : fields) {
    
            Object value =field.get(condition);
            if(null != value){
    
                if(String.class == field.getType()) {
    
                    where.append(" and " + fieldMapper.get(field.getName()) + " = '" + value + "'");
                }else{
    
                    where.append(" and " + fieldMapper.get(field.getName()) + " = " + value + "");
                }
                // Others are not listed here , We'll write it later ORM The framework will be improved 
            }
        }
        System.out.println(sql + where.toString());
        pstm =  con.prepareStatement(sql + where.toString());

        //4.  Execution statement set 
        rs = pstm.executeQuery();

        // Metadata ?
        // All additional information other than processing real values is saved 
        int columnCounts = rs.getMetaData().getColumnCount();
        while (rs.next()){
    
            Object instance = entityClass.newInstance();
            for (int i = 1; i <= columnCounts; i++) {
    
                // Entity class property name , The field name of the corresponding database table 
                // You can get all the fields of the entity class through the reflection mechanism 

                // from rs Get the class name under the current cursor 
                String columnName = rs.getMetaData().getColumnName(i);
                // It could be private 
                Field field = entityClass.getDeclaredField(columnMapper.get(columnName));
                field.setAccessible(true);
                field.set(instance,rs.getObject(columnName));
            }

            result.add(instance);

        }

        //5.  Get the result set 
    }catch (Exception e){
    
        e.printStackTrace();
    }
    //6.  Close result set 、 Close statement set 、 Close the connection 
    finally {
    
        try {
    
            rs.close();
            pstm.close();
            con.close();
        }catch (Exception e){
    
            e.printStackTrace();
        }
    }

    return result;
}

The above skillfully uses the reflection mechanism to read Class Information and Annotation Information , Associatively map and assign values to the columns in the database table and the fields in the class , To reduce duplicate code .

1.2 Why ORM frame

Through the previous explanation , We already know ORM The basic implementation principle of the framework .ORM Refers to object relational mapping (Object Relation Mapping), Mapping is not just object values , And the relationship between objects , For example, one to many 、 Many to many 、 A one-to-one table relationship . Now on the market ORM There are also many frameworks , There are well-known Hibernate、Spring JDBC、MyBatis、JPA etc. . Here's a brief summary , As shown in the following table .

name features describe
Hibernate Fully automatic ( block ) You don't need to write a sentence SQL
MyBatis semi-automatic ( block ) Hands are one , Support simple mapping , Complex relationships need to be written by yourself SQL
Spring JDBC Pure manual ( block ) be-all SQL Write it yourself , It helps us design a standard process

Since there are so many choices on the market , Why should I write it myself ORM What about the framework ?
This has to start with my experience as an architect in an airborne . The biggest problem faced by airborne is how to get the team “ friends ” The trust of the . at that time , The team has a total of 8 people , Everyone's level is uneven , Some people haven't even touched MySQL, Such as Redis Wait for caching middleware, let alone . Basically only use Hibernate Of CRUD, And it has affected the system performance . Due to the tight schedule , No time and energy to do systematic training for the team , Also in order to give consideration to controllability , So there is self research ORM The idea of a framework . I made such a top-level design , To reduce team “ friends ” The cost of saving interest , Unified parameters of top-level interface 、 Uniform return value , As follows .

**(1) The interface model of the specified query method is : **


/** *  To obtain a list of  * @param queryRule  Query criteria  * @return */
List<T> select(QueryRule queryRule) throws Exception;

/** *  Get paging results  * @param queryRule  Query criteria  * @param pageNo  Page number  * @param pageSize  Number of entries per page  * @return */
Page<?> select(QueryRule queryRule,int pageNo,int pageSize) throws Exception;

/** *  according to SQL To obtain a list of  * @param sql SQL sentence  * @param args  Parameters  * @return */
List<Map<String,Object>> selectBySql(String sql, Object... args) throws Exception;

/** *  according to SQL Get paging  * @param sql SQL sentence  * @param pageNo  Page number  * @param pageSize  Number of entries per page  * @return */
Page<Map<String,Object>> selectBySqlToPage(String sql, Object [] param, int pageNo, int pageSize) throws Exception;

(2) The interface model that specifies the deletion method is :


/** *  Delete a record  * @param entity entity Medium ID Can't be empty , If ID It's empty , Other conditions cannot be empty , All are empty and will not be executed  * @return */
boolean delete(T entity) throws Exception;

/** *  Batch deletion  * @param list * @return  Returns the number of affected rows  * @throws Exception */
int deleteAll(List<T> list) throws Exception;

(3) The interface model that specifies the insertion method is :


/** *  Insert a record and return the inserted ID * @param entity  as long as entity It's not equal to null, Just insert  * @return */
PK insertAndReturnId(T entity) throws Exception;

/** *  Insert a record and add it automatically ID * @param entity * @return * @throws Exception */
boolean insert(T entity) throws Exception;

/** *  Batch insert  * @param list * @return  Returns the number of affected rows  * @throws Exception */
int insertAll(List<T> list) throws Exception;

(4) The interface model specifying the modification method is :


/** *  Modify a record  * @param entity entity Medium ID Can't be empty , If ID It's empty , Other conditions cannot be empty , All are empty and will not be executed  * @return * @throws Exception */
boolean update(T entity) throws Exception;

Take advantage of this basic API, Later, I based on Redis、MongoDB、ElasticSearch、Hive、HBase Each package has a set , So as to reduce the learning cost of the team , It also greatly improves the controllability of the program , More convenient for unified monitoring .

2 Build the infrastructure

2.1 Page

Definition Page The main purpose of class is to provide top-level support for the unified return results of later paging queries , Its main functions include the encapsulation of paging logic 、 Paging data .


package javax.core.common;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

/** *  Paging object , Contains the current page data and paging information , Such as the total number of records  *  Able to support and JQuery EasyUI Direct docking , Able to support and BootStrap Table Direct docking  */
public class Page<T> implements Serializable {
    

   private static final long serialVersionUID = 1L;
   private static final int DEFAULT_PAGE_SIZE = 20;

   private int pageSize = DEFAULT_PAGE_SIZE; // Records per page 

   private long start; // The first data on the current page is in List Position in , from 0 Start 

   private List<T> rows; // Records stored in the current page , The type is generally List

   private long total; // Total number of records 

   /** *  Construction method , Construct only empty pages  */
   public Page() {
    
      this(0, 0, DEFAULT_PAGE_SIZE, new ArrayList<T>());
   }

   /** *  Default constructor  * * @param start  The starting position of the data on this page in the database  * @param totalSize  Total number of records in the database  * @param pageSize  Capacity of this page  * @param rows  This page contains data  */
   public Page(long start, long totalSize, int pageSize, List<T> rows) {
    
      this.pageSize = pageSize;
      this.start = start;
      this.total = totalSize;
      this.rows = rows;
   }

   /** *  Take the total number of records  */
   public long getTotal() {
    
      return this.total;
   }
   
   public void setTotal(long total) {
    
      this.total = total;
   }

   /** *  Take the total number of pages  */
   public long getTotalPageCount() {
    
      if (total % pageSize == 0){
    
         return total / pageSize;
      }else{
    
         return total / pageSize + 1;
      }
   }

   /** *  Take the data capacity of each page  */
   public int getPageSize() {
    
      return pageSize;
   }

   /** *  Take the record in the current page  */
   public List<T> getRows() {
    
      return rows;
   }
   
   public void setRows(List<T> rows) {
    
      this.rows = rows;
   }

   /** *  Take the current page number of this page , Page number from 1 Start  */
   public long getPageNo() {
    
      return start / pageSize + 1;
   }

   /** *  Does this page have a next page  */
   public boolean hasNextPage() {
    
      return this.getPageNo() < this.getTotalPageCount() - 1;
   }

   /** *  Whether this page has a previous page  */
   public boolean hasPreviousPage() {
    
      return this.getPageNo() > 1;
   }

   /** *  Get the position of the first data on any page in the dataset , The number of entries per page uses the default value  * * @see #getStartOfPage(int,int) */
   protected static int getStartOfPage(int pageNo) {
    
      return getStartOfPage(pageNo, DEFAULT_PAGE_SIZE);
   }

   /** *  Get the position of the first data on any page in the dataset  * * @param pageNo  from 1 Start page number  * @param pageSize  Number of records per page  * @return  The first data on this page  */
   public static int getStartOfPage(int pageNo, int pageSize) {
    
      return (pageNo - 1) * pageSize;
   }

}

2.2 ResultMsg

ResultMsg Class is mainly the top-level design for unified return results , It mainly includes the status code 、 Result description and return data .


package javax.core.common;

import java.io.Serializable;

// Bottom design 
public class ResultMsg<T> implements Serializable {
    

   private static final long serialVersionUID = 2635002588308355785L;

   private int status; // Status code , The return code of the system 
   private String msg;  // Explanation of status code 
   private T data;  // Put any result 

   public ResultMsg() {
    }
   
   public ResultMsg(int status) {
    
      this.status = status;
   }

   public ResultMsg(int status, String msg) {
    
      this.status = status;
      this.msg = msg;
   }
   
   public ResultMsg(int status, T data) {
    
      this.status = status;
      this.data = data;
   }

   public ResultMsg(int status, String msg, T data) {
    
      this.status = status;
      this.msg = msg;
      this.data = data;
   }

   public int getStatus() {
    
      return status;
   }

   public void setStatus(int status) {
    
      this.status = status;
   }

   public String getMsg() {
    
      return msg;
   }

   public void setMsg(String msg) {
    
      this.msg = msg;
   }

   public T getData() {
    
      return data;
   }

   public void setData(T data) {
    
      this.data = data;
   }

}

2.3 BaseDao

As all BaseDao The top-level interface of the persistence framework , The main definition is 、 Delete 、 Change 、 Check the unified parameter list and return value .


package javax.core.common.jdbc;

import com.gupaoedu.vip.orm.framework.QueryRule;

import javax.core.common.Page;
import java.util.List;
import java.util.Map;

public interface BaseDao<T,PK> {
    
    /** *  To obtain a list of  * @param queryRule  Query criteria  * @return */
    List<T> select(QueryRule queryRule) throws Exception;

    /** *  Get paging results  * @param queryRule  Query criteria  * @param pageNo  Page number  * @param pageSize  Number of entries per page  * @return */
    Page<?> select(QueryRule queryRule,int pageNo,int pageSize) throws Exception;

    /** *  according to SQL To obtain a list of  * @param sql SQL sentence  * @param args  Parameters  * @return */
    List<Map<String,Object>> selectBySql(String sql, Object... args) throws Exception;

    /** *  according to SQL Get paging  * @param sql SQL sentence  * @param pageNo  Page number  * @param pageSize  Number of entries per page  * @return */
    Page<Map<String,Object>> selectBySqlToPage(String sql, Object [] param, int pageNo, int pageSize) throws Exception;

    /** *  Delete a record  * @param entity entity Medium ID Can't be empty , If ID It's empty , Other conditions cannot be empty , If it is empty, it will not be executed  * @return */
    boolean delete(T entity) throws Exception;

    /** *  Batch deletion  * @param list * @return  Returns the number of affected rows  * @throws Exception */
    int deleteAll(List<T> list) throws Exception;

    /** *  Insert a record and return the inserted ID * @param entity  as long as entity It's not equal to null, Just perform the insertion operation  * @return */
    PK insertAndReturnId(T entity) throws Exception;

    /** *  Insert a record and add it automatically ID * @param entity * @return * @throws Exception */
    boolean insert(T entity) throws Exception;

    /** *  Batch insert  * @param list * @return  Returns the number of affected rows  * @throws Exception */
    int insertAll(List<T> list) throws Exception;

    /** *  Modify a record  * @param entity entity Medium ID Can't be empty , If ID It's empty , Other conditions cannot be empty , If it is empty, it will not be executed  * @return * @throws Exception */
    boolean update(T entity) throws Exception;
}

2.4 QueryRule

If you use QueryRule Class to build query criteria , Users do not need to write when making conditional queries SQL, Implement business code and SQL decoupling .


package com.gupaoedu.vip.orm.framework;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

/** * QueryRule, The main function is used to construct query conditions  */
public final class QueryRule implements Serializable
{
    
   private static final long serialVersionUID = 1L;
   public static final int ASC_ORDER = 101;
   public static final int DESC_ORDER = 102;
   public static final int LIKE = 1;
   public static final int IN = 2;
   public static final int NOTIN = 3;
   public static final int BETWEEN = 4;
   public static final int EQ = 5;
   public static final int NOTEQ = 6;
   public static final int GT = 7;
   public static final int GE = 8;
   public static final int LT = 9;
   public static final int LE = 10;
   public static final int ISNULL = 11;
   public static final int ISNOTNULL = 12;
   public static final int ISEMPTY = 13;
   public static final int ISNOTEMPTY = 14;
   public static final int AND = 201;
   public static final int OR = 202;
   private List<Rule> ruleList = new ArrayList<Rule>();
   private List<QueryRule> queryRuleList = new ArrayList<QueryRule>();
   private String propertyName;

   private QueryRule() {
    }

   private QueryRule(String propertyName) {
    
      this.propertyName = propertyName;
   }

   public static QueryRule getInstance() {
    
      return new QueryRule();
   }
   
   /** *  Add ascending rules  * @param propertyName * @return */
   public QueryRule addAscOrder(String propertyName) {
    
      this.ruleList.add(new Rule(ASC_ORDER, propertyName));
      return this;
   }

   /** *  Add descending rule  * @param propertyName * @return */
   public QueryRule addDescOrder(String propertyName) {
    
      this.ruleList.add(new Rule(DESC_ORDER, propertyName));
      return this;
   }

   public QueryRule andIsNull(String propertyName) {
    
      this.ruleList.add(new Rule(ISNULL, propertyName).setAndOr(AND));
      return this;
   }

   public QueryRule andIsNotNull(String propertyName) {
    
      this.ruleList.add(new Rule(ISNOTNULL, propertyName).setAndOr(AND));
      return this;
   }

   public QueryRule andIsEmpty(String propertyName) {
    
      this.ruleList.add(new Rule(ISEMPTY, propertyName).setAndOr(AND));
      return this;
   }

   public QueryRule andIsNotEmpty(String propertyName) {
    
      this.ruleList.add(new Rule(ISNOTEMPTY, propertyName).setAndOr(AND));
      return this;
   }

   public QueryRule andLike(String propertyName, Object value) {
    
      this.ruleList.add(new Rule(LIKE, propertyName, new Object[] {
     value }).setAndOr(AND));
      return this;
   }

   public QueryRule andEqual(String propertyName, Object value) {
    
      this.ruleList.add(new Rule(EQ, propertyName, new Object[] {
     value }).setAndOr(AND));
      return this;
   }

   public QueryRule andBetween(String propertyName, Object... values) {
    
      this.ruleList.add(new Rule(BETWEEN, propertyName, values).setAndOr(AND));
      return this;
   }

   public QueryRule andIn(String propertyName, List<Object> values) {
    
      this.ruleList.add(new Rule(IN, propertyName, new Object[] {
     values }).setAndOr(AND));
      return this;
   }

   public QueryRule andIn(String propertyName, Object... values) {
    
      this.ruleList.add(new Rule(IN, propertyName, values).setAndOr(AND));
      return this;
   }
   
   public QueryRule andNotIn(String propertyName, List<Object> values) {
    
      this.ruleList.add(new Rule(NOTIN, propertyName, new Object[] {
     values }).setAndOr(AND));
      return this;
   }

   public QueryRule orNotIn(String propertyName, Object... values) {
    
      this.ruleList.add(new Rule(NOTIN, propertyName, values).setAndOr(OR));
      return this;
   }
   

   public QueryRule andNotEqual(String propertyName, Object value) {
    
      this.ruleList.add(new Rule(NOTEQ, propertyName, new Object[] {
     value }).setAndOr(AND));
      return this;
   }

   public QueryRule andGreaterThan(String propertyName, Object value) {
    
      this.ruleList.add(new Rule(GT, propertyName, new Object[] {
     value }).setAndOr(AND));
      return this;
   }

   public QueryRule andGreaterEqual(String propertyName, Object value) {
    
      this.ruleList.add(new Rule(GE, propertyName, new Object[] {
     value }).setAndOr(AND));
      return this;
   }

   public QueryRule andLessThan(String propertyName, Object value) {
    
      this.ruleList.add(new Rule(LT, propertyName, new Object[] {
     value }).setAndOr(AND));
      return this;
   }

   public QueryRule andLessEqual(String propertyName, Object value) {
    
      this.ruleList.add(new Rule(LE, propertyName, new Object[] {
     value }).setAndOr(AND));
      return this;
   }
   
   
   public QueryRule orIsNull(String propertyName) {
    
      this.ruleList.add(new Rule(ISNULL, propertyName).setAndOr(OR));
      return this;
   }

   public QueryRule orIsNotNull(String propertyName) {
    
      this.ruleList.add(new Rule(ISNOTNULL, propertyName).setAndOr(OR));
      return this;
   }

   public QueryRule orIsEmpty(String propertyName) {
    
      this.ruleList.add(new Rule(ISEMPTY, propertyName).setAndOr(OR));
      return this;
   }

   public QueryRule orIsNotEmpty(String propertyName) {
    
      this.ruleList.add(new Rule(ISNOTEMPTY, propertyName).setAndOr(OR));
      return this;
   }

   public QueryRule orLike(String propertyName, Object value) {
    
      this.ruleList.add(new Rule(LIKE, propertyName, new Object[] {
     value }).setAndOr(OR));
      return this;
   }

   public QueryRule orEqual(String propertyName, Object value) {
    
      this.ruleList.add(new Rule(EQ, propertyName, new Object[] {
     value }).setAndOr(OR));
      return this;
   }

   public QueryRule orBetween(String propertyName, Object... values) {
    
      this.ruleList.add(new Rule(BETWEEN, propertyName, values).setAndOr(OR));
      return this;
   }

   public QueryRule orIn(String propertyName, List<Object> values) {
    
      this.ruleList.add(new Rule(IN, propertyName, new Object[] {
     values }).setAndOr(OR));
      return this;
   }

   public QueryRule orIn(String propertyName, Object... values) {
    
      this.ruleList.add(new Rule(IN, propertyName, values).setAndOr(OR));
      return this;
   }

   public QueryRule orNotEqual(String propertyName, Object value) {
    
      this.ruleList.add(new Rule(NOTEQ, propertyName, new Object[] {
     value }).setAndOr(OR));
      return this;
   }

   public QueryRule orGreaterThan(String propertyName, Object value) {
    
      this.ruleList.add(new Rule(GT, propertyName, new Object[] {
     value }).setAndOr(OR));
      return this;
   }

   public QueryRule orGreaterEqual(String propertyName, Object value) {
    
      this.ruleList.add(new Rule(GE, propertyName, new Object[] {
     value }).setAndOr(OR));
      return this;
   }

   public QueryRule orLessThan(String propertyName, Object value) {
    
      this.ruleList.add(new Rule(LT, propertyName, new Object[] {
     value }).setAndOr(OR));
      return this;
   }

   public QueryRule orLessEqual(String propertyName, Object value) {
    
      this.ruleList.add(new Rule(LE, propertyName, new Object[] {
     value }).setAndOr(OR));
      return this;
   }
   

   public List<Rule> getRuleList() {
    
      return this.ruleList;
   }

   public List<QueryRule> getQueryRuleList() {
    
      return this.queryRuleList;
   }

   public String getPropertyName() {
    
      return this.propertyName;
   }

   protected class Rule implements Serializable {
    
      private static final long serialVersionUID = 1L;
      private int type;  // Type of rule 
      private String property_name;
      private Object[] values;
      private int andOr = AND;

      public Rule(int paramInt, String paramString) {
    
         this.property_name = paramString;
         this.type = paramInt;
      }

      public Rule(int paramInt, String paramString,
            Object[] paramArrayOfObject) {
    
         this.property_name = paramString;
         this.values = paramArrayOfObject;
         this.type = paramInt;
      }
      
      public Rule setAndOr(int andOr){
    
         this.andOr = andOr;
         return this;
      }
      
      public int getAndOr(){
    
         return this.andOr;
      }

      public Object[] getValues() {
    
         return this.values;
      }

      public int getType() {
    
         return this.type;
      }

      public String getPropertyName() {
    
         return this.property_name;
      }
   }
}

2.5 Order

Order Class is mainly used to encapsulate sorting rules , The code is as follows :


package com.gupaoedu.vip.orm.framework;

/** * SQL Sort components  */
public class Order {
    
   private boolean ascending; // Ascending or descending 
   private String propertyName; // Which field is in ascending order , Which field is in descending order 
   
   public String toString() {
    
      return propertyName + ' ' + (ascending ? "asc" : "desc");
   }

   /** * Constructor for Order. */
   protected Order(String propertyName, boolean ascending) {
    
      this.propertyName = propertyName;
      this.ascending = ascending;
   }

   /** * Ascending order * * @param propertyName * @return Order */
   public static Order asc(String propertyName) {
    
      return new Order(propertyName, true);
   }

   /** * Descending order * * @param propertyName * @return Order */
   public static Order desc(String propertyName) {
    
      return new Order(propertyName, false);
   }
}

Because of the length , Specific operation classes continue in the next article .
Pay attention to WeChat public number 『 Tom Bomb architecture 』 reply “Spring” The complete source code is available .

 Insert picture description here

This paper is about “Tom Bomb architecture ” original , Reprint please indicate the source . Technology is about sharing , I share my happiness !
If you have any suggestions, you can also leave comments or private letters , Your support is the driving force for me to adhere to my creation . Pay attention to WeChat public number 『 Tom Bomb architecture 』 More technical dry goods are available !

Originality is not easy. , Persistence is cool , You can see it here , Little buddy, remember to praise 、 Collection 、 Looking at , One click three times plus attention ! If you think the content is too dry , You can share and forward it to friends !

copyright notice
author[Tom bomb architecture],Please bring the original link to reprint, thank you.
https://en.cdmana.com/2022/01/202201270117037555.html

Random recommended