Ebean 字段别名配置引发语法问题

news2025/2/25 22:07:31

前言

Ebean 没听过?这里简单给你介绍下:Ebean 是一个 Java ORM(Object-Relational Mapping)框架,具有以下优势:

  1. 简单易用:Ebean 的 API 设计简单易用,可以快速上手,无需繁琐的配置。

  2. 自动化 SQL 生成:Ebean 可以自动化生成 SQL 语句,开发者无需手写 SQL,提高了开发效率。

  3. 高性能:Ebean 的性能优秀,支持缓存、预编译等优化手段,可以快速处理大量数据。

  4. 多数据源支持:Ebean 支持多数据源,可以同时连接多个数据库,方便应用在不同环境下的部署和迁移。

  5. 事务管理:Ebean 提供了完整的事务管理机制,保证数据的一致性和可靠性。

  6. 灵活的查询:Ebean 支持灵活的查询方式,可以根据需求灵活组合条件、排序和分页等操作。

简单来说,Ebean 是一个功能丰富、易于使用且性能优越的 ORM 框架,适用于各种规模的 Java 项目,尤其是丰富的流式 API 封装,使用很丝滑,举个例子:

// "alias" bean that can be used in select and fetch clauses
QCustomer cust = QCustomer.alias();

List<Customer> customers =
  new QCustomer()
    // only fetch some properties of customer (partial objects)
    .select(cust.name, cust.version, cust.whenCreated)
    .name.istartsWith("Rob")
    .findList();

项目场景:

最近接手一个项目,持久层就使用了 Ebean 框架。刚接手的项目,你懂的,总有一些坑需要你去踩!

需求很简答:要对查询结果字段做去重并统计总数,很简单的问题,直接翻译成代码即可:

        int count = queryBean()
                .select(QCallRecord.alias().contentId)
                .type.eq("user")
                .setDistinct(true)
                .findCount();

正常情况下,这样使用就 OK 了


问题描述

问题来了:

Caused by: java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; 
check the manual that corresponds to your MySQL server version 
for the right syntax to use near 'c0) from call_record t0 where t0.type = 'user'' at line 1

也就是语法有问题,我们看看生成的 SQL 语法:

select count(distinct t0.content_id c0) from call_record t0 where t0.type = 'user'

问题在哪? 字段 content_id 的别名。

在 MySQL 中,对于 count 这类聚合函数内是不允许出现字段别名,别名 c0 是在函数参数中定义的,这是一种错误的写法,会导致语法错误。

正确的写法应该是将 AS 关键字放在函数后面,比如:

SELECT count(DISTINCT t0.content_id) AS c0 FROM call_record t0 WHERE t0.type = 'user';

更深层原因?

SQL 聚合函数是作用于某个列或表达式的数据集上,并计算这些值的总和、平均值、最小值、最大值等等。因此,在 SQL 查询中,聚合函数的参数应该是列或表达式,而不是别名。


原因分析:

Ebean 怎么会解析出有语法问题的 SQL?是bug 还是配置问题?

Ebean 提供了 DatabasePlatform 这么一个数据库平台抽象类,它定义了一系列通用的接口和方法,以便与不同的数据库进行交互,具体差异由子类去个性化实现,你可以看看:

在这里插入图片描述

有多少是自己熟悉的数据库?

不同的数据库难免有些差异,比如 MySQL、Postgres 等,当然 Ebean 已经把这些差异化都实现了,默认情况下自动选择,对使用者来说无感知!!! 除非你特性化需求配置。

当然,我就遇到了。DB 自定义配置项:

    @Override
    public Database getObject() throws Exception {
        DatabaseConfig databaseConfig = new DatabaseConfig();
        
        ...
        
        DatabasePlatform dbPlatform = new DatabasePlatform();
        dbPlatform.getDbIdentity().setIdType(IdType.IDENTITY);
        dbPlatform.getDbIdentity().setSupportsGetGeneratedKeys(true);
        dbPlatform.getDbIdentity().setSupportsSequence(false);
        dbPlatform.getDbIdentity().setSupportsIdentity(true);
        databaseConfig.setDatabasePlatform(dbPlatform);
 
        ...

        return DatabaseFactory.create(databaseConfig);
    }

项目里手动配置这几个参数,但是配置不够完整,部分适用于 MySQL 的默认配置没有加上,比如我们这缺失的 :

        dbPlatform.setColumnAliasPrefix(null);

不过查看 Ebean 对于 MySQL 的默认配置:

在这里插入图片描述

你看,默认的参数和手动配置参数值的是否一样?同时也更加完善,大部分时候,默认配置可能都是最优解。


解决方案:

新增配置项:

  dbPlatform.setColumnAliasPrefix(null);

取消这种默认定义别名的方式,最后的正确的 SQL 语法:

select count(distinct t0.content_id) from call_record t0 where t0.type = 'user';

当然,也不排除这个本身是 Ebean 的问题,可以进一步做的更好,比如改进聚合函数取别名的方式等。




不同框架在底层细节实现上可能有些不同,但一般都留足了可扩展的口子,提供给你去定制化使用;当然,如非必要,直接使用默认配置可能是最优解!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/520915.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

OpenGL高级-GLSL

引言 我们会讨论一些内建变量(Built-in Variable)、组织着色器输入和输出的新方式以及一个叫做uniform缓冲对象(Uniform Buffer Object)的非常有用的工具。 GLSL的内建变量 着色器是很小的&#xff0c;如果我们需要从当前着色器以外的别的资源里的数据&#xff0c;那么我们就不…

ChatGPT系列学习(1)transformer基本原理讲解

文章目录 1. 简介1.1. 发展史 2. Transformer 整体结构3. 名词解释3.1. token 4. transformer输入4.1. 单词 Embedding4.2. 位置Embedding4.3. Transformer Embedding层实现 5. Attention结构5.1. 简介5.2. Self Attention&#xff08;自注意力机制&#xff09;5.2.1. 简介5.2.…

Python 密码破解指南:20~24

协议&#xff1a;CC BY-NC-SA 4.0 译者&#xff1a;飞龙 本文来自【OpenDocCN 饱和式翻译计划】&#xff0c;采用译后编辑&#xff08;MTPE&#xff09;流程来尽可能提升效率。 收割 SB 的人会被 SB 们封神&#xff0c;试图唤醒 SB 的人是 SB 眼中的 SB。——SB 第三定律 二十、…

HashMap源码和原理

HashMap源码分析 重要变量: Node<K,V>[] table 存放单链表头结点的数组size 存储结点数量threshold 阈值,通过size和threshold比较来做扩容loadFactor 加载因子 重要方法: put(K key, V value) 添加结点get(Object key) 查询结点 单链表Node结点中的一些变量: hash …

《程序员面试金典(第6版)》面试题 16.20. T9键盘(哈希映射,C++)

题目描述 在老式手机上&#xff0c;用户通过数字键盘输入&#xff0c;手机将提供与这些数字相匹配的单词列表。每个数字映射到0至4个字母。给定一个数字序列&#xff0c;实现一个算法来返回匹配单词的列表。你会得到一张含有有效单词的列表。&#xff08;原题链接&#xff09; …

程序的灵魂-数据结构

1、数据结构 程序 数据结构 算法 1.1、何为数据结构? 数据结构是计算机底层存储、组织数据的方式。是指数据相互之间是以什么方式排列在一起的 数据结构是为了更加方便的管理和使用数据&#xff0c;需要结合具体的业务场景来进行选择 通常情况下&#xff0c;精心选择的数…

爆肝一周,我开源了ChatGPT 中文版接口,官方1:1镜像支持全部 官方接口

这里实现我之前文章承诺承接上文 人人实现ChatGPT自由&#xff0c;手把手教你零撸部署自己聊天私服 现在ChatGPT 提供了api接口 可以让我自己对接去实现我们自己想要gpt应用&#xff0c;但是由于一些原因&#xff0c;国内也不开放接口&#xff0c;所以我就1:1 自己对接了官方…

计算机毕业论文内容参考|基于java的研发部署管理平台的设计与实现

文章目录 导文文章重点摘要前言绪论课题背景国内外现状与趋势课题内容应用程序生命周期管理。相关技术与方法介绍系统分析系统设计系统实现系统测试总结和展望本文总结后续工作展望导文 基于java的研发部署管理平台的设计与实现 文章重点 摘要 本文介绍了基于Java的研发部署管…

UNIAPP实战项目笔记71 订单到支付和生成订单号的前后端交互

UNIAPP实战项目笔记71 订单到支付和生成订单号的前后端交互 思路 购物车页面点击结算 发送请求: 传递商品数据 前端就拿到了订单号进行存储 并且跳转到确认订单页面 后端 生成一个订单,并且返回给前端一个订单号 确认订单页面 点击提交订单 前端 判断是否选择了收货地址 …

QT+OpenCV 编译成功

VSQTOpenCV 真费劲 忙活半天算是有效果了 #include "opencv2/opencv.hpp"; using namespace cv;Demo1::Demo1(QWidget* parent): QMainWindow(parent) {ui.setupUi(this);connect(ui.btn, SIGNAL(clicked()), this, SLOT(Btn1Click())); }void Demo1::Btn1Click() {Q…

如何动态的测试Thrift服务

​RPC协议与Thrift框架 RPC&#xff08;Remote Procedure Call&#xff0c;远程过程调用&#xff09;是一种通信协议&#xff0c;用于不同的进程或计算机之间进行通信和交互。它允许应用程序在本地或远程计算机上调用另一个应用程序中的函数或方法&#xff0c;就像调用本地函数…

asp.net+sqlserver校园超市进销存管理系统的开发与设计

随校园超市管理系统功能&#xff1a;包括&#xff0c;管理员登录、员工登录&#xff1b;商品信息管理&#xff0c;能够查看商品的基本信息&#xff0c;对商品的基本信息进行修改&#xff1b;员工信息管理&#xff0c;管理员工基本信息&#xff0c;设置与不同的权限&#xff0c;…

【Selenium中】——全栈开发——如桃花来

目录索引 查找元素&#xff1a;查找方法&#xff1a;单个元素查找&#xff1a;多个元素查找&#xff1a;*代码演示&#xff1a;* 元素交互操作&#xff1a;清空文字&#xff1a; 推荐的变量名定义名称&#xff1a;执行JavaScript &#xff1a;滚动页面方法&#xff1a;*滚动到底…

NetCore发布到Docker-局域网

1.说明: 1) 目标&#xff0c;NetCore 项目通过Jenkins发布到局域网的服务器上 2) 单机版的请参考 https://mp.csdn.net/mp_blog/creation/editor/130619862 2.安装插件 Publish Over SSH 1) Dashboard -> Manage Jenkins -> 插件管 2) 安装完之后 2.添加SSH服务器 1) …

【重磅分享】免梯子GPT,教你玩转GPT正确姿势

火了一周的 ChatGPT&#xff0c;xd 不允许还有小伙伴不知道这个东西是什么&#xff1f;简单来说就是&#xff0c;你可以让它扮演任何事物&#xff0c;据说已经有人用它开始了颜色文学创作。因为它太火了&#xff0c;所以&#xff0c;本周特推在几十个带有“chatgpt”的项目中选…

VOC标签格式转yolo格式并划分训练集和测试集

目录 一、了解VOC数据格式 1、Annotations目录 2. JPEGImages目录 二、YOLO格式 三、VOC标签格式转yolo格式并划分训练集和测试集 一、了解VOC数据格式 Pascal VOC数据集下载地址&#xff1a;The PASCAL Visual Object Classes Homepage 介绍一下VOC 数据集下载后的目录结构…

Vue(动画、过渡、动画库)

一、动画 1.使用场景 在插入、更新或者移除DOM元素时候&#xff0c;在合适的时候给元素添加样式类型。 2. 使用 首先在组件style创建出现和离开的动画 然后对动画进行处理&#xff08;命名注意是v-enter-action和v-leave-action&#xff09; 如果name命名在默认标签中使用之后…

Redis高可用系列——ZSet类型底层详解

文章目录 概述skiplistredis的skiplist 概述 Redis 中的 zset 是一种有序集合类型&#xff0c;它可以存储不重复的字符串元素&#xff0c;并且给每个元素赋予一个排序权重值&#xff08;score&#xff09;。Redis 通过权重值来为集合中的元素进行从小到大的排序。zset 的成员是…

一、H3C-NE实验-Telnet实验

实验环境&#xff1a; 1. 在电脑搜索栏&#xff0c;搜“程序”&#xff0c;确保Telnet服务开启 2. 防火墙处于关闭状态 实验工具&#xff1a;H3C Cloud Lab、SecureCRT 实验拓扑&#xff1a; 实验步骤&#xff1a; 1. 登录路由器&#xff0c;配置路由器相关信息&#xff0c;…

【容器化】Docker 使用Ⅰ

【容器化】Docker 使用Ⅰ Docker Hello World运行交互式的容器启动容器&#xff08;后台模式&#xff09;停止容器Docker 的使用获取镜像启动容器后台运行停止一个容器进入容器导出和导入容器删除容器运行一个 web 应用查看 WEB 应用容器网络端口的快捷方式查看 WEB 应用程序日…