{"id":1182,"date":"2024-12-30T18:31:06","date_gmt":"2024-12-30T10:31:06","guid":{"rendered":"http:\/\/www.max-shu.com\/blog\/?p=1182"},"modified":"2024-12-30T18:31:08","modified_gmt":"2024-12-30T10:31:08","slug":"springboot-jpa%e5%ae%9e%e7%8e%b0%e5%af%b9%e6%95%b0%e6%8d%ae%e5%ba%93%e8%a1%a8%e7%bb%9f%e4%b8%80%e7%9a%84%e5%a2%9e%e5%88%a0%e6%94%b9%e6%9f%a5","status":"publish","type":"post","link":"http:\/\/www.max-shu.com\/blog\/?p=1182","title":{"rendered":"Springboot JPA\u5b9e\u73b0\u5bf9\u6570\u636e\u5e93\u8868\u7edf\u4e00\u7684\u589e\u5220\u6539\u67e5"},"content":{"rendered":"\n<p><strong>\u9996\u5148\u5efa\u7acb\u4e00\u4e2a\u516c\u5171\u7684BaseEntity\u5bf9\u5e94\u6570\u636e\u5e93\u4e2d\u7684\u8868\u683c\u516c\u5171\u5b57\u6bb5\uff0c\u5176\u4ed6Entity\u90fd\u4ece\u5b83\u7ee7\u627f\uff1a<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">@Data<br>@MappedSuperclass<br>public class BaseEntity implements Serializable {<br>    private static final long <em>serialVersionUID <\/em>= 1L;<br>    @Id<br>    @GeneratedValue(strategy = GenerationType.<em>IDENTITY<\/em>)<br>    @Column(name = \"_id\")<br>    protected Long id;<br><br>    @Column(name = \"create_time\", columnDefinition = \"datetime COMMENT '\u521b\u5efa\u65f6\u95f4'\")<br>    @Temporal(<em>TIMESTAMP<\/em>)<br>    @CreationTimestamp<br>    protected Date createTime;<br><br>    @Column(name = \"update_time\", columnDefinition = \"datetime COMMENT '\u4fee\u6539\u65f6\u95f4\u65f6\u95f4'\")<br>    @Temporal(<em>TIMESTAMP<\/em>)<br>    @UpdateTimestamp<br>    protected Date updateTime;<br>}<\/pre>\n\n\n\n<p><strong>\u7136\u540e\u518d\u5efa\u7acb\u4e00\u4e2a\u516c\u5171\u7684BaseDto\uff0c\u7528\u4e8e\u5bf9\u5e94BaseEntity\u7684\u5404\u5b57\u6bb5\uff1a<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">@Data<br>public class BaseDTO implements Serializable {<br>    protected Long id;<br>    @JSONField(format = \"yyyy-MM-dd HH:mm:ss\")<br>    protected Date createdTime;<br>    @JSONField(format = \"yyyy-MM-dd HH:mm:ss\")<br>    protected Date updateTime;<br><br>    public String[] uniqueKeys() {<br>        return null;<br>    }<br><br>}<\/pre>\n\n\n\n<p><strong>\u8fd8\u5f97\u5efa\u7acb\u4e00\u4e2aBaseRepository\u7684Repository\u63a5\u53e3\uff0c\u7528\u4e8e\u64cd\u4f5c\u6570\u636e\u5e93\uff1a<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">@NoRepositoryBean<br>public interface BaseRepository&lt;T> extends JpaRepository&lt;T, Long>, JpaSpecificationExecutor&lt;T>, QueryByExampleExecutor&lt;T> {<br>}<br><br><strong>\u6700\u540e\u5efa\u7acbBaseController\u7c7b\uff08\u6216\u8005BaseService\u4e5f\u53ef\u4ee5\uff0c\u540e\u7eed\u6839\u636e\u63a7\u5236\u7c7b\u8fd8\u662f\u670d\u52a1\u7c7b\u53bb\u7ee7\u627f\u5c31\u597d\u4e86\uff09\uff0c\u7528\u4e8e\u5b9e\u73b0\u516c\u5171\u7684\u589e\u5220\u6539\u67e5\u64cd\u4f5c\uff1a<\/strong><br>public class BaseController&lt;E extends BaseEntity, S extends BaseRepository&lt;E>, T extends BaseDTO> {<br>    private final Logger logger = LoggerFactory.getLogger(BaseController.class);<br>    private String classTName;<br>    private S repo;<br><br>    @Autowired<br>    private EntityManager entityManager;<br><br>    public BaseController(Class&lt;?> classT, S repo){<br>        this.classTName = classT.getSimpleName();<br>        this.repo = repo;<br>    }<br><br>    public E dto2Entity(T dto){ \/\/\u5b9e\u9645\u8c03\u7528\u65f6\u5c06\u88ab\u5b50\u7c7b\u540c\u540d\u65b9\u6cd5\u66ff\u6362<br>        logger.error(\"Shoud not be called.\");<br>        return null;<br>    }<br><br>    public T entity2Dto(E entity){ \/\/\u5b9e\u9645\u8c03\u7528\u65f6\u5c06\u88ab\u5b50\u7c7b\u540c\u540d\u65b9\u6cd5\u66ff\u6362<br>        logger.error(\"Shoud not be called.\");<br>        return null;<br>    }<br><br><br>    @RequestMapping(value = \"\/all\", method = {RequestMethod.GET})<br>    public BaseBodyResponse all() {<br>        logger.info(\"All {}.\", classTName);<br>        List&lt;E> entityList = repo.findAll();<br>        List&lt;T> dtoList = new ArrayList&lt;>();<br>        if(entityList != null) {<br>            for (E entity : entityList) {<br>                T dto = entity2Dto(entity);<br>                dtoList.add(dto);<br>            }<br>        }<br>        return new BaseBodyResponse(true, \"\", dtoList);<br>    }<br><br>    \/\/\u53ea\u652f\u6301String\u7c7b\u578b\u7684\u5b57\u6bb5\uff0c\u6839\u636e\u5b57\u6bb5\u540d\u8fd4\u56dedistinct list&lt;string>\u3002<br>    @RequestMapping(value = \"\/allbyfield\", method = {RequestMethod.GET})<br>    public BaseBodyResponse allByField(@RequestParam String field) {<br>        logger.info(\"AllByField {}:{}\", classTName, field);<br>        Type genType = this.getClass().getGenericSuperclass();<br>        if(!(genType instanceof ParameterizedType)) {<br>            return new BaseBodyResponse(false, \"Server error!\");<br>        }<br>        Type[] params = ((ParameterizedType) genType).getActualTypeArguments();<br>        if (!(params[0] instanceof Class)){<br>            return new BaseBodyResponse(false, \"Server error!\");<br>        }<br>        Class entityClass = (Class)params[0]; \/\/0\u5c31\u662f\u5c31\u662f\u672c\u7c7b\u7684\u7b2c\u4e00\u4e2a\u53c2\u6570\u6a21\u677f\u7c7b\uff0c\u5373E\u3002<br>        CriteriaBuilder cb = entityManager.getCriteriaBuilder();<br>        CriteriaQuery&lt;String> query = cb.createQuery(String.class);<br>        Root&lt;String> root = query.from(entityClass);<br>        query.multiselect(root.get(field)).distinct(true);<br>        query.where(cb.equal(cb.literal(1), 1));<br>        List&lt;String> fieldValueList = entityManager.createQuery(query).getResultList();<br>        return new BaseBodyResponse(true, \"\", fieldValueList);<br>    }<br><br><br>    @RequestMapping(value = \"\/add\", method = {RequestMethod.POST})<br>    public BaseResponse add(@RequestBody T model) {<br>        logger.info(\"Add {}:{}\", classTName, JSON.toJSONString(model));<br>        BaseResponse resp = new BaseResponse(false, \"\u6dfb\u52a0\u5931\u8d25\");<br>        T uniqueObj = getUniqueObj(model);<br>        if (null != uniqueObj) {<br>            logger.error(\"Data has exist, {}\", JSON.toJSONString(model));<br>            resp.update(false, \"\u6570\u636e\u5df2\u7ecf\u5b58\u5728\");<br>        }else {<br>            model.setId(null);<br>            repo.save(this.dto2Entity(model));<br>            resp.update(true, \"\u6dfb\u52a0\u6210\u529f\");<br>        }<br>        return resp;<br>    }<br><br>    private T getUniqueObj(T model) {<br>        String[] uniqueKeys = model.uniqueKeys();<br>        if (uniqueKeys != null &amp;&amp; uniqueKeys.length > 0) {<br>            Specification&lt;E> specification = (Root&lt;E> root, CriteriaQuery&lt;?> query, CriteriaBuilder cb) -> {<br>                List&lt;Predicate> predicateList = new ArrayList&lt;>();<br>                for (String fieldName : uniqueKeys) {<br>                    Object fieldValue = getFieldValueByName(model, fieldName);<br>                    predicateList.add(cb.equal(root.get(fieldName), fieldValue));<br>                }<br>                if(predicateList != null &amp;&amp; !predicateList.isEmpty()) {<br>                    Predicate[] predicateArray = new Predicate[predicateList.size()];<br>                    predicateList.toArray(predicateArray);<br>                    query.where(cb.and(predicateArray));<br>                }<br>                return query.getRestriction();<br>            };<br>            Optional&lt;E> entity = repo.findOne(specification); \/\/\u5b9e\u9645specification\u5728\u8fd9\u91cc\u624d\u4f1a\u53bb\u8ba1\u7b97\u3002<br>            if(entity.isPresent()) {<br>                return this.entity2Dto(entity.get());<br>            }<br>        }<br>        return null;<br>    }<br><br>    private Object getFieldValueByName(Object o, String fieldName){<br>        String firstLetter = fieldName.substring(0, 1).toUpperCase();<br>        String getter = \"get\" + firstLetter + fieldName.substring(1);<br>        try {<br>            Method method = o.getClass().getMethod(getter, new Class[]{});<br>            Object value = method.invoke(o, new Object[]{});<br>            return value;<br>        }catch (Exception e){<br>            logger.error(\"Exception: \"+e.getMessage(), e);<br>        }<br>        return null;<br>    }<br><br><br>    @RequestMapping(value = \"\/delete\", method = {RequestMethod.GET})<br>    public BaseResponse delete(@RequestParam Long id) {<br>        logger.info(\"Delete {}:{}\", classTName, id);<br>        Optional&lt;E> entity = repo.findById(id);<br>        if (entity.isPresent()) {<br>            repo.deleteById(id);<br>            return new BaseResponse(true, \"\u5220\u9664\u6210\u529f\");<br>        } else {<br>            return new BaseResponse(false, \"\u6570\u636e\u4e0d\u5b58\u5728\");<br>        }<br>    }<br><br><br>    @RequestMapping(value = \"\/edit\", method = {RequestMethod.POST})<br>    public BaseResponse edit(@RequestBody T model) {<br>        logger.info(\"Edit {} :{}\", classTName, JSON.toJSONString(model));<br>        BaseResponse resp = new BaseResponse(false, \"\u4fee\u6539\u5931\u8d25\");<br>        T uniqueObj = getUniqueObj(model);<br>        if (null != uniqueObj &amp;&amp; !uniqueObj.getId().equals(model.getId())) {<br>            logger.error(\"Data has exist And ID not match\", JSON.toJSONString(model));<br>            resp.setMessage(\"\u6570\u636e\u51b2\u7a81\");<br>        } else {<br>            E entity = this.dto2Entity(model);<br>            repo.save(entity);<br>            resp.update(true, \"\u4fee\u6539\u6210\u529f\");<br>        }<br>        return resp;<br>    }<br><br><br>    @RequestMapping(value = \"\/load\", method = {RequestMethod.GET})<br>    public BaseBodyResponse load(@RequestParam Long id) {<br>        logger.info(\"Load {}:{}\", classTName, id);<br>        Optional&lt;E> entity = repo.findById(id);<br>        if(entity.isPresent()) {<br>            T dto = this.entity2Dto(entity.get());<br>            return new BaseBodyResponse(true, \"\", dto);<br>        }else {<br>            return new BaseBodyResponse(false, \"\u6570\u636e\u4e0d\u5b58\u5728\");<br>        }<br>    }<br><br>    @GetMapping(\"\/page\")<br>    public YunResult page(<br>        @RequestParam(name = \"pageSize\", required = true) Integer pageSize,<br>        @RequestParam(name = \"pageNum\", required = true) Integer pageNum,<br>        @RequestParam(name = \"total\", required = false) Integer total,<br>        @RequestParam(name = \"sidx\", required = false) List&lt;String> sidx, \/\/\u6392\u5e8f\u5b57\u6bb5\u540d<br>        @RequestParam(name = \"sord\", required = false) List&lt;String> sord, \/\/ desc \u6216 asc<br>        @RequestParam(name = \"filters\", required = false) String filters \/\/ \u8fc7\u6ee4\u5b57\u6bb5<br>    ) {<br>        \/\/ pageSize=15&amp;pageNum=1<br>        \/\/ pageSize=15&amp;pageNum=1&amp;total=0&amp;sidx=XX&amp;sord=DESC&amp;sidx=YY&amp;sord=ASC&amp;filters=<br>        \/\/ pageSize=15&amp;pageNum=1&amp;filters=%7B%22groupOp%22%3A%22AND%22%2C%22rules%22%3A%5B%7B%22groupOp%22%3A%22or%22%2C%22rules%22%3A%5B%7B%22field%22%3A%22channel%22%2C%22op%22%3A%22eq%22%2C%22data%22%3A%22facebook%22%7D%2C%7B%22field%22%3A%22opResult%22%2C%22op%22%3A%22eq%22%2C%22data%22%3A%22ALL%22%7D%5D%7D%2C%7B%22field%22%3A%22channel%22%2C%22op%22%3A%22eq%22%2C%22data%22%3A%22facebook%22%7D%2C%7B%22field%22%3A%22status%22%2C%22op%22%3A%22eq%22%2C%22data%22%3Atrue%7D%5D%7D<br>        \/\/ \u4e0a\u9762\u7684filters\u53c2\u6570\u662fjson\u65b9\u5f0f\uff0c\u7136\u540eurlEncode\u7f16\u7801\u540e\u7684\u503c\u3002<br>        logger.info(\"Page {}: pageSize: {}, pageNum: {}, total: {}, sidx: {}, sord: {}, filters: {}\",<br>            classTName, pageSize, pageNum, total, sidx, sord, filters);<br><br>        \/\/\u5904\u7406Page\u5206\u9875 \u3001Sort\u6392\u5e8f \u548cSpecification\u8fc7\u6ee4<br>        PageRequest pageRequest = this.getPageRequest(pageSize, pageNum, sidx, sord);<br>        Specification&lt;E> specification = this.getSpecification(filters);<br><br>        \/\/\u5904\u7406\u7ed3\u679c<br>        Page&lt;E> page = repo.findAll(specification, pageRequest); \/\/\u5b9e\u9645specification\u5728\u8fd9\u91cc\u624d\u4f1a\u53bb\u8ba1\u7b97\u3002<br>        SimplePageView&lt;T> pageView = new SimplePageView&lt;>(pageNum, pageSize);<br>        if (page != null) {<br>            List&lt;T> dtoList = new ArrayList&lt;>();<br>            List&lt;E> entityList = page.getContent();<br>            for(E entity: entityList){<br>                dtoList.add(this.entity2Dto(entity));<br>            }<br>            pageView.setData(dtoList);<br>            pageView.setTotal(page.getTotalElements());<br>        } else {<br>            pageView.setData(null);<br>            pageView.setTotal(0L);<br>        }<br>        return YunResult.success(pageView);<br>    }<br><br>    \/\/\u5904\u7406Page\u5206\u9875 \u548cSort\u6392\u5e8f<br>    public PageRequest getPageRequest(Integer pageSize, Integer pageNum, List&lt;String> sidx, List&lt;String> sord){<br>        PageRequest pageRequest = null;<br>        if(sidx != null &amp;&amp; (!sidx.isEmpty())) {<br>            List&lt;Sort.Order> orderList = new ArrayList&lt;>();<br>            for(int i = 0; i&lt; sidx.size(); i++) {<br>                Sort.Order order = null;<br>                if(sord != null &amp;&amp; (!sord.isEmpty()) &amp;&amp; sord.get(i) != null) {<br>                    order = new Sort.Order(Sort.Direction.fromString(sord.get(i)), sidx.get(i));<br>                } else{<br>                    order = new Sort.Order(Sort.Direction.ASC, sidx.get(i));<br>                }<br>                orderList.add(order);<br>            }<br>            Sort sort = Sort.by(orderList);<br>            pageRequest = PageRequest.of(pageNum - 1, pageSize, sort);<br>        }else{<br>            pageRequest = PageRequest.of(pageNum - 1, pageSize);<br>        }<br>        return pageRequest;<br>    }<br><br>    \/\/\u5904\u7406Specification\u8fc7\u6ee4\uff08SQL\u7684where\u5b57\u53e5\uff09<br>    \/\/\u8bf4\u660e\uff1a<br>    \/\/\u8f93\u5165\u4f8b\u5b50\uff1a {\"groupOp\":\"AND\",\"rules\":[{\"groupOp\":\"or\",\"rules\":[{\"field\":\"channel\",\"op\":\"eq\",\"data\":\"facebook\"},{\"field\":\"opResult\",\"op\":\"eq\",\"data\":\"ALL\"}]},{\"field\":\"channel\",\"op\":\"eq\",\"data\":\"facebook\"},{\"field\":\"status\",\"op\":\"eq\",\"data\":true}]}<br>    \/\/\u76f8\u5f53\u4e8e\uff1a where (channel=facebook or op_result=ALL) and channel=facebook and status=TRUE<br>    \/\/\u679a\u4e3e\u5b57\u6bb5\u503c\u8981\u7528'String'\u65b9\u5f0f\u6620\u5c04\uff1bboolean\u5b57\u6bb5\u503c\u8981\u7528json\u7684true\/false\u6765\u4f20\u5165\u3002<br>    \/\/\u652f\u6301\u7684op\u64cd\u4f5c(\u4e0d\u533a\u5206\u5927\u5c0f\u5199)\uff1ais null, is not null, eq, neq, like, not like, in, not in, gt, ge, lt, le, \u4e0d\u652f\u6301between\u3002<br>    \/\/\u652f\u6301\u7684grougOp\u64cd\u4f5c(\u4e0d\u533a\u5206\u5927\u5c0f\u5199)\uff1aand, or, not\u3002<br>    public Specification&lt;E> getSpecification(String filters) {<br>        return  (Root&lt;E> root, CriteriaQuery&lt;?> query, CriteriaBuilder cb) -> {<br>            Predicate predicate = this.buildPredicateRecursion(filters, root, cb);<br>            \/\/Predicate predicateTrue = cb.equal(cb.literal(1), 1);<br>            if(predicate != null) {<br>                query.where(cb.and(predicate));<br>                return query.getRestriction();<br>            }<br>            return null;<br>        };<br>    }<br>    private Predicate buildPredicateRecursion(String filters,<br>                                         Root&lt;E> root, CriteriaBuilder cb) {<br>        Predicate predicate = null;<br>        if(StringUtils.isNoneBlank(filters)) {<br>            JSONObject jsonObject = JSONObject.parseObject(filters);<br>            String groupOp = jsonObject.getString(\"groupOp\");<br>            if(StringUtils.isNoneBlank(groupOp)){<br>                JSONArray rules = (JSONArray) jsonObject.get(\"rules\");<br>                if(rules != null){<br>                    List&lt;Predicate> predicateListTmp = new ArrayList&lt;Predicate>();<br>                    for(int i=0 ;i &lt; rules.size(); i++){<br>                        JSONObject rule = rules.getJSONObject(i);<br>                        String groupOpTmp = rule.getString(\"groupOp\");<br>                        Predicate predicateTmp = null;<br>                        if(StringUtils.isNoneBlank(groupOpTmp)) { \/\/\u9012\u5f52\u5904\u7406\u5e26groupOn\u7684\u6761\u4ef6\uff0c\u5b9e\u9645\u5c31\u662f\u5b9e\u73b0\u4e86\u62ec\u53f7\u64cd\u4f5c\u7b26\u7684\u4f5c\u7528<br>                            predicateTmp = this.buildPredicateRecursion(rule.toString(), root, cb);<br>                        }else { \/\/\u5904\u7406\u4e0d\u5e26groupOn\u7684\u6761\u4ef6<br>                            predicateTmp = this.getPredicate(root, cb, rule);<br>                        }<br>                        if(predicateTmp != null) {<br>                            predicateListTmp.add(predicateTmp);<br>                        }else{<br>                            logger.error(\"{} predicateTmp is null or empty.\", classTName);<br>                        }<br>                    }<br>                    if(predicateListTmp != null &amp;&amp; !predicateListTmp.isEmpty()) {<br>                        Predicate[] predicateArray = new Predicate[predicateListTmp.size()];<br>                        predicateListTmp.toArray(predicateArray);<br>                        switch (groupOp.toLowerCase()) {<br>                            case \"and\":<br>                                predicate = cb.and(predicateArray);<br>                                break;<br>                            case \"or\":<br>                                predicate = cb.or(predicateArray);<br>                                break;<br>                            case \"not\":<br>                                predicate = cb.not(predicateArray[0]);<br>                                break;<br>                            default:<br>                                logger.error(\"{} Not support groupOn: {}\", classTName, groupOp);<br>                                break;<br>                        }<br>                    }<br>                }else{<br>                    logger.error(\"{} rules is null or empty.\", classTName);<br>                }<br>            }else {<br>                logger.error(\"{} groupOn is null or empty.\", classTName);<br>            }<br>        }<br>        return predicate;<br>    }<br>    private Predicate getPredicate(Root&lt;E> root, CriteriaBuilder cb, JSONObject jsonObject){<br>        String field = jsonObject.getString(\"field\");<br>        String op = jsonObject.getString(\"op\");<br>        Object data = jsonObject.get(\"data\");<br>        String className = jsonObject.get(\"data\").getClass().getSimpleName();<br>        Predicate predicate = null;<br>        switch (op.toLowerCase()) {<br>            case \"is null\":<br>                predicate = cb.isNull(root.get(field));<br>                break;<br>            case \"is not null\":<br>                predicate = cb.isNotNull(root.get(field));<br>                break;<br>            case \"eq\":<br>                predicate = cb.equal(root.get(field), data);<br>                break;<br>            case \"neq\":<br>                predicate = cb.notEqual(root.get(field), data);<br>                break;<br>            case \"like\":<br>                predicate = cb.like(root.get(field).as(String.class), jsonObject.getString(\"data\"));<br>                break;<br>            case \"not like\":<br>                predicate = cb.notLike(root.get(field).as(String.class), jsonObject.getString(\"data\"));<br>                break;<br>            case \"in\":<br>                if(className.toLowerCase().equals(\"string\")) {<br>                    CriteriaBuilder.In&lt;String> inClause = cb.in(root.get(field).as(String.class));<br>                    for (String inStr : jsonObject.getString(field).split(\",\")) {<br>                        inClause.value(inStr);<br>                    }<br>                    predicate = inClause;<br>                }else{<br>                    logger.error(\"{} Only support string type for 'in' op.\", classTName);<br>                }<br>                break;<br>            case \"not in\":<br>                if(className.toLowerCase().equals(\"string\")) {<br>                    CriteriaBuilder.In&lt;String> inClause = cb.in(root.get(field).as(String.class));<br>                    for (String inStr : jsonObject.getString(field).split(\",\")) {<br>                        inClause.value(inStr);<br>                    }<br>                    predicate = cb.not(inClause);<br>                }else{<br>                    logger.error(\"{} Only support string type for 'in' op.\", classTName);<br>                }<br>                break;<br>            case \"gt\":<br>                switch (className.toLowerCase()) {<br>                    case \"integer\":<br>                        Integer dataInt = jsonObject.getInteger(\"data\");<br>                        predicate = cb.gt(root.get(field).as(Integer.class), dataInt);<br>                        break;<br>                    case \"long\":<br>                        Long dataLong = jsonObject.getLong(\"data\");<br>                        predicate = cb.gt(root.get(field).as(Long.class), dataLong);<br>                        break;<br>                    case \"double\":<br>                        Double dataDouble = jsonObject.getDouble(\"data\");<br>                        predicate = cb.gt(root.get(field).as(Double.class), dataDouble);<br>                        break;<br>                    case \"float\":<br>                        Float dataFloat = jsonObject.getFloat(\"data\");<br>                        predicate = cb.gt(root.get(field).as(Float.class), dataFloat);<br>                        break;<br>                    default:<br>                        logger.error(\"{} Not support calssName: {}\", classTName, className);<br>                }<br>                break;<br>            case \"ge\":<br>                switch (className.toLowerCase()) {<br>                    case \"integer\":<br>                        Integer dataInt = jsonObject.getInteger(\"data\");<br>                        predicate = cb.ge(root.get(field).as(Integer.class), dataInt);<br>                        break;<br>                    case \"long\":<br>                        Long dataLong = jsonObject.getLong(\"data\");<br>                        predicate = cb.ge(root.get(field).as(Long.class), dataLong);<br>                        break;<br>                    case \"double\":<br>                        Double dataDouble = jsonObject.getDouble(\"data\");<br>                        predicate = cb.ge(root.get(field).as(Double.class), dataDouble);<br>                        break;<br>                    case \"float\":<br>                        Float dataFloat = jsonObject.getFloat(\"data\");<br>                        predicate = cb.gt(root.get(field).as(Float.class), dataFloat);<br>                        break;<br>                    default:<br>                        logger.error(\"{} Not support calssName: {}\", classTName, className);<br>                }<br>                break;<br>            case \"lt\":<br>                switch (className.toLowerCase()) {<br>                    case \"integer\":<br>                        Integer dataInt = jsonObject.getInteger(\"data\");<br>                        predicate = cb.lt(root.get(field).as(Integer.class), dataInt);<br>                        break;<br>                    case \"long\":<br>                        Long dataLong = jsonObject.getLong(\"data\");<br>                        predicate = cb.lt(root.get(field).as(Long.class), dataLong);<br>                        break;<br>                    case \"double\":<br>                        Double dataDouble = jsonObject.getDouble(\"data\");<br>                        predicate = cb.lt(root.get(field).as(Double.class), dataDouble);<br>                        break;<br>                    case \"float\":<br>                        Float dataFloat = jsonObject.getFloat(\"data\");<br>                        predicate = cb.gt(root.get(field).as(Float.class), dataFloat);<br>                        break;<br>                    default:<br>                        logger.error(\"{} Not support calssName: {}\", classTName, className);<br>                }<br>                break;<br>            case \"le\":<br>                switch (className.toLowerCase()) {<br>                    case \"integer\":<br>                        Integer dataInt = jsonObject.getInteger(\"data\");<br>                        predicate = cb.le(root.get(field).as(Integer.class), dataInt);<br>                        break;<br>                    case \"long\":<br>                        Long dataLong = jsonObject.getLong(\"data\");<br>                        predicate = cb.le(root.get(field).as(Long.class), dataLong);<br>                        break;<br>                    case \"double\":<br>                        Double dataDouble = jsonObject.getDouble(\"data\");<br>                        predicate = cb.le(root.get(field).as(Double.class), dataDouble);<br>                        break;<br>                    case \"float\":<br>                        Float dataFloat = jsonObject.getFloat(\"data\");<br>                        predicate = cb.gt(root.get(field).as(Float.class), dataFloat);<br>                        break;<br>                    default:<br>                        logger.error(\"{} Not support calssName: {}\", classTName, className);<br>                }<br>                break;<br>            default:<br>                logger.error(\"{} Not support op: {}\", classTName, op);<br>                break;<br>        }<br>        return predicate;<br>    }<br>}<br><br><strong>\u540e\u7eed\u5177\u4f53\u5230\u5404\u4e2a\u8868\u65f6\u6269\u5c55\u4e0a\u9762\u7684\u5404\u4e2a\u7c7b\u5373\u53ef\uff0c\u6bd4\u5982\u6709\u4e2aTest\u8868\u9700\u8981\u589e\u5220\u6539\u67e5\uff0c\u90a3\u4e48\uff1a<\/strong><br>TestEntity\u7c7b extends BaseEntity\uff1b<br>TestDto\u7c7b extends BaseDto;<br>TestRepo\u7c7b extends BaseRepository&lt;TestEntity><br><br><em>\u63a7\u5236\u7c7b\uff1a<\/em><br>@RestController<br>@RequestMapping(\"\/a_database\/test\")<br>public class TestController extends BaseController&lt;TestEntity, TestEntityRepo, TestDto>{<br>    private final Logger logger = LoggerFactory.getLogger(TestController.class);<br><br>    private TestEntityRepo repo;<br><br>    public TestController(TestEntityRepo repo){<br>        super(TestController.class, repo);<br>        this.repo = repo;<br>    }<br><br>    @Override<br>    public TestEntity dto2Entity(TestDto dto){ \/\/\u5fc5\u987b\u5b9e\u73b0<br>        TestEntity entity = new TestEntity();<br>        BeanUtils.copyProperties(dto, entity);<br>        return entity;<br>    }<br>    @Override<br>    public TestDto entity2Dto(TestEntity entity){ \/\/\u5fc5\u987b\u5b9e\u73b0<br>        TestDto dto = new TestDto();<br>        BeanUtils.copyProperties(entity, dto);<br>        return dto;<br>    }<br><br>}<br><br>\u8bf4\u660e\uff1a\u4e0a\u8ff0\u4ee3\u7801\u4e2d\u7684BaseResponse\u3001BaseBodyResponse\u3001YunResult\u53ea\u662f\u7528\u6765\u88c5\u8f7d\u8fd4\u56de\u7684\u6570\u636e\u7684\uff0c\u5c31\u4e0d\u518d\u5217\u51fa\u4ee3\u7801\u4e86\u3002<br><br><strong>\u6d4b\u8bd5\uff1a<\/strong><br>\u6839\u636e\u4e3b\u952eid\u5f97\u5230\u67d0\u6761\u5177\u4f53\u8bb0\u5f55\uff1ahttp:\/\/127.0.0.1:80\/a_database\/test\/load?id=2<br>\u5176\u4ed6\u5206\u9875page\u3001edit\u3001add\u3001delete\u3001all\u3001allbyfield\u64cd\u4f5c\u7c7b\u4f3c\uff0c\u53c2\u8003BaseController\u4ee3\u7801\u5373\u53ef\u3002<br><br><\/pre>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u9996\u5148\u5efa\u7acb\u4e00\u4e2a\u516c\u5171\u7684BaseEntity\u5bf9\u5e94\u6570\u636e\u5e93\u4e2d\u7684\u8868\u683c\u516c\u5171\u5b57\u6bb5\uff0c\u5176\u4ed6Entity\u90fd\u4ece\u5b83\u7ee7\u627f\uff1a @Data@M &hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[63,13],"tags":[934,933,931,929,932,877,930,61],"class_list":["post-1182","post","type-post","status-publish","format-standard","hentry","category-63","category-13","tag-criterialbuilder","tag-criteriaquery","tag-entitymanager","tag-jpa","tag-specification","tag-springboot","tag-930","tag-61"],"views":736,"_links":{"self":[{"href":"http:\/\/www.max-shu.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1182","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.max-shu.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.max-shu.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.max-shu.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.max-shu.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1182"}],"version-history":[{"count":1,"href":"http:\/\/www.max-shu.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1182\/revisions"}],"predecessor-version":[{"id":1183,"href":"http:\/\/www.max-shu.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1182\/revisions\/1183"}],"wp:attachment":[{"href":"http:\/\/www.max-shu.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1182"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.max-shu.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1182"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.max-shu.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1182"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}