Spring JPA执行原生SQL查询时出现MySQL语法错误求助
解决Spring JPA原生查询的MySQLSyntaxErrorException问题
这个语法错误的根源其实很常见——你在Java代码里拼接SQL字符串时,部分片段的结尾/开头没有添加空格,导致SQL关键字和字段/表名被错误地连在一起。虽然你手动在MySQL里执行的SQL是正确的,但字符串拼接后生成的SQL已经出现了语法问题,比如:
- 最后一个查询字段
f.facPlaca后面没有空格,直接跟了from,拼接后变成f.facPlacafrom factura f...,这直接违反了SQL语法。 - 还有
parametros p后面直接接where,变成parametros pwhere c.tipDocId...,这也是明显的语法错误点。
下面是具体的修复方案:
1. 修复字符串拼接的空格问题
确保每个SQL片段的结尾都保留空格,这样拼接后不会出现内容连在一起的情况。修正后的Repository代码如下:
@Repository public interface FacturaRepository extends JpaRepository<Factura, Integer>, CrudRepository<Factura, Integer>{ @Query(value="select " + "f.facId," + "facBaja," + "f.facEnvioSunat," + "f.facEnvioServidor," + "f.facEstadoEnvioCorreo," + "f.facFechaRespuesta," + "f.facRuta," + "f.facSubTotal," + "f.facInafecta," + "f.facExonerada," + "f.facGratuita," + "f.facGravada," + "f.facPercepcion," + "f.facOtrosTributos," + "f.facDescuento," + "cl.codLeyCodigo," + "f.facLeyenda," + "f.facDetraccion," + "f.facNroSerie," + "f.facNroCorrelativo," + "f.facFechaEmision," + "tc.tipComCodigo,"+ "m.monCodigo,"+ "ub.ubiDepartamento," + "ub.ubiProvincia," + "ub.ubiDistrito," + "ub.ubiCodigo," + "p.parRuta," + "s.sucDireccionFiscal," + "s.sucRuc," + "s.sucTipoDocumento," + "s.sucPais," + "s.sucRazonSocial," + "c.cliCondicionDomicilio," + "c.cliDireccionFiscal," + "c.cliEstado," + "c.cliNumeroDocumento," + "c.cliRazonSocial," + "td.tipDocCodigo," + "f.facIgv," + "f.facIsc," + "ttig.tipTaxIgvCodigo," + "ttis.tipTaxIscCodigo," + "f.facOtrosConceptos," + "oc.otrConCodigo," + "f.facTaxIgvPorcentaje," + "f.facTaxIscPorcentaje," + "f.facHashcode," + "f.facNombreZip," + "f.facTotal," + "f.facRetencion," + "f.facPlaca " + // 这里添加空格 "from factura f, codigoleyenda cl, tipocomprobante tc, moneda m, cliente c, tipotaxigv ttig, tipotaxisc ttis, otrosconceptos oc, " + // 逗号后添加空格 "tipodocumento td, sucursal s, ubigeo ub, parametros p " + // 这里添加空格 "where c.tipDocId = td.tipDocId and f.sucId=s.sucId and s.ubiId=ub.ubiId and s.parId=p.parId " + // 这里添加空格 "and f.codLeyId=cl.codLeyId and f.tipComId=tc.tipComId and f.monId=m.monId and f.cliId=c.cliId and " + "f.tipTaxIgvId=ttig.tipTaxIgvId and f.tipTaxIscId=ttis.tipTaxIscId and f.OtrConId=oc.otrConId and f.facId=?1", nativeQuery=true) FacturaXmlDto getFacturaXml(int facId); }
2. 推荐使用Java Text Blocks(Java 15+)简化编写
如果你的项目使用Java 15及以上版本,强烈建议用Text Blocks来编写多行SQL,彻底避免字符串拼接的空格问题,代码可读性也会大幅提升:
@Repository public interface FacturaRepository extends JpaRepository<Factura, Integer>, CrudRepository<Factura, Integer>{ @Query(value=""" select f.facId, facBaja, f.facEnvioSunat, f.facEnvioServidor, f.facEstadoEnvioCorreo, f.facFechaRespuesta, f.facRuta, f.facSubTotal, f.facInafecta, f.facExonerada, f.facGratuita, f.facGravada, f.facPercepcion, f.facOtrosTributos, f.facDescuento, cl.codLeyCodigo, f.facLeyenda, f.facDetraccion, f.facNroSerie, f.facNroCorrelativo, f.facFechaEmision, tc.tipComCodigo, m.monCodigo, ub.ubiDepartamento, ub.ubiProvincia, ub.ubiDistrito, ub.ubiCodigo, p.parRuta, s.sucDireccionFiscal, s.sucRuc, s.sucTipoDocumento, s.sucPais, s.sucRazonSocial, c.cliCondicionDomicilio, c.cliDireccionFiscal, c.cliEstado, c.cliNumeroDocumento, c.cliRazonSocial, td.tipDocCodigo, f.facIgv, f.facIsc, ttig.tipTaxIgvCodigo, ttis.tipTaxIscCodigo, f.facOtrosConceptos, oc.otrConCodigo, f.facTaxIgvPorcentaje, f.facTaxIscPorcentaje, f.facHashcode, f.facNombreZip, f.facTotal, f.facRetencion, f.facPlaca from factura f, codigoleyenda cl, tipocomprobante tc, moneda m, cliente c, tipotaxigv ttig, tipotaxisc ttis, otrosconceptos oc, tipodocumento td, sucursal s, ubigeo ub, parametros p where c.tipDocId = td.tipDocId and f.sucId=s.sucId and s.ubiId=ub.ubiId and s.parId=p.parId and f.codLeyId=cl.codLeyId and f.tipComId=tc.tipComId and f.monId=m.monId and f.cliId=c.cliId and f.tipTaxIgvId=ttig.tipTaxIgvId and f.tipTaxIscId=ttis.tipTaxIscId and f.OtrConId=oc.otrConId and f.facId=?1 """, nativeQuery=true) FacturaXmlDto getFacturaXml(int facId); }
3. 额外建议:改用显式JOIN语法
你当前使用的是隐式连接(逗号分隔表),虽然能正常运行,但显式JOIN语法的可读性更强,也更容易排查关联条件的问题,示例如下:
from factura f join codigoleyenda cl on f.codLeyId = cl.codLeyId join tipocomprobante tc on f.tipComId = tc.tipComId join moneda m on f.monId = m.monId join cliente c on f.cliId = c.cliId -- 其他表的JOIN依次补充关联条件
这样修改后,你的Spring JPA原生查询应该就能正常执行了,不会再触发语法错误。
内容的提问来源于stack exchange,提问作者Juan Copara
相关产品推荐
相关产品推荐

