JDBC 类型没有方言映射:1111
No Dialect mapping for JDBC type: 1111
我正在开发 Spring JPA 应用程序,使用 MySQL 作为数据库。我确保加载了所有 spring-jpa 库、hibernate 和 mysql-connector-java。
我是 运行 一个 mysql 5 实例。这是我的 application.properties 文件的摘录:
spring.jpa.show-sql=false
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.database-platform=org.hibernate.dialect.MySQL5Dialect
spring.datasource.url=jdbc:mysql://localhost/mydatabase
spring.datasource.username=myuser
spring.datasource.password=SUPERSECRET
spring.datasource.driverClassName=com.mysql.jdbc.Driver
执行集成测试时,spring 正常启动但无法创建休眠 SessionFactory,例外情况是:
org.hibernate.MappingException: No Dialect mapping for JDBC type: 1111
我认为我的方言应该是 Mysql5Dialect,我也尝试了明确说明 InnoDB 的方言,以及两个不指示版本 5 的方言选项。但我总是得到相同的 'No Dialect mapping for JDBC type: 1111' 消息.
我的 application.properties 文件位于 test/resources 源文件夹中。它被 JUnit 测试运行器识别(我之前因为其中的拼写错误而出现异常)。
是我设置的属性有误吗?我找不到关于这些 属性 名称的一些官方文档,但在这个 Whosebug 答案中找到了提示:
期待您的回答,谢谢!
顺便说一句,该应用程序已经在使用 spring 引导。
这里是基于 SubOptimal 的评论的答案:
错误信息实际上是说一个列类型不能被hibernate映射到一个数据库类型。
在我的例子中,它是我在我的一些实体中用作主键的 java.util.UUID
类型。只需应用注释 @Type(type="uuid-char")
(对于 postgres @Type(type="pg-uuid")
)
还有另一个常见的用例抛出此异常。调用 returns void
的函数。有关更多信息和解决方案,请转到 here.
有时当您调用 sql procedure/function 时,可能需要 return 一些东西。您可以尝试 returning void: RETURN;
或 string(这个对我有用):RETURN 'OK'
请检查某些列 return 中是否有许多 未知类型 在查询中。
例如:'1' as column_name 可以有未知类型
和1因为column_name是整数是正确的一.
这东西对我有用。
对于使用旧休眠 (3.x) 版本遇到此错误的任何人:
不要用大写字母写return类型。 hibernate 类型实现映射使用小写 return 类型并且不转换它们:
CREATE OR REPLACE FUNCTION do_something(param varchar)
RETURNS integer AS
$BODY$
...
在我的例子中,问题是我在我的用户 class 中设置存储过程时忘记添加 resultClasses 属性。
@NamedStoredProcedureQuery(name = "find_email",
procedureName = "find_email", resultClasses = User.class, //<--I forgot that.
parameters = {
@StoredProcedureParameter(mode = ParameterMode.IN, name = "param_email", type = String.class)
}),
我遇到了同样的错误,因为我的查询返回了一个 UUID 列。为了解决这个问题,我通过 "cast(columnName as varchar)" 之类的查询将 UUID 列作为 varchar 类型返回,然后它起作用了。
示例:
public interface StudRepository extends JpaRepository<Mark, UUID> {
@Modifying
@Query(value = "SELECT Cast(stuid as varchar) id, SUM(marks) as marks FROM studs where group by stuid", nativeQuery = true)
List<Student> findMarkGroupByStuid();
public static interface Student(){
private String getId();
private String getMarks();
}
}
当您使用 Hibernate 和 returning void 函数时也会发生这种情况。至少有 postgres。它不知道如何处理 void。我最终不得不将 void 更改为 return int.
如果您使用的是 Postgres,请检查您是否没有 Abstime 类型的列。 Abstime 是 JPA 无法识别的内部 Postgres 数据类型。在这种情况下,如果您的业务要求允许,使用 TO_CHAR 转换为文本可能 有所帮助。
如果您有原生 SQL 查询,则通过向查询添加转换来修复它。
例子:
CAST('yourString' AS varchar(50)) as anyColumnName
就我而言,它对我有用。
这是 Hibernate (5.x) 版本
正在调用数据库函数 return JSON string/object
为此使用 unwrap(org.hibernate.query.NativeQuery.class).addScalar()
相同的方法。
示例如下(Spring & 休眠):
@PersistenceContext
EntityManager em;
@Override
public String getJson(String strLayerName) {
String *nativeQuery* = "select fn_layer_attributes(:layername)";
return em.createNativeQuery(*nativeQuery*).setParameter("layername", strLayerName).**unwrap(org.hibernate.query.NativeQuery.class).addScalar**("fn_layer_attributes", **new JsonNodeBinaryType()**) .getSingleResult().toString();
}
查找触发问题的列
首先,您没有提供实体映射,因此我们无法判断是哪个列产生了这个问题。例如,它可以是 UUID
或 JSON
列。
现在,您使用的是非常古老的 Hibernate 方言。 MySQL5Dialect
适用于 MySQL 5。很可能您使用的是较新的 MySQL 版本。
因此,尝试使用 MySQL8Dialect
代替:
spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect
添加非标准类型
如果您因为使用 JSON 列类型而遇到问题,请尝试提供支持非标准类型的自定义 Hibernate 方言:
public class MySQL8JsonDialect
extends MySQL8Dialect{
public MySQL8JsonDialect() {
super();
this.registerHibernateType(
Types.OTHER, JsonStringType.class.getName()
);
}
}
答案使用自定义 Hibernate 方言:
<property
name="hibernate.dialect"
value="com.vladmihalcea.book.hpjp.hibernate.type.json.MySQL8JsonDialect"
/>
如果在执行 SQL 本地查询时出现此异常,则需要通过 addScalar
:
传递类型
JsonNode properties = (JsonNode) entityManager
.createNativeQuery(
"SELECT properties " +
"FROM book " +
"WHERE isbn = :isbn")
.setParameter("isbn", "978-9730228236")
.unwrap(org.hibernate.query.NativeQuery.class)
.addScalar("properties", JsonStringType.INSTANCE)
.getSingleResult();
assertEquals(
"High-Performance Java Persistence",
properties.get("title").asText()
);
我得到了同样的错误,这里的问题是存储在数据库中的 UUID 没有转换为对象。
我尝试应用这些注释@Type(type="uuid-char")(对于 postgres @Type(type="pg-uuid")但它对我不起作用。
这对我有用。假设您想要来自 table 的 id 和 name 以及 JPA 中的本机查询。使用字段 id 和 name 创建一个实体 class,例如 'User',然后尝试将 object[] 转换为我们想要的实体。这里匹配的数据是我们从查询中获得的对象数组列表。
@Query( value = "SELECT CAST(id as varchar) id, name from users ", nativeQuery = true)
public List<Object[]> search();
public class User{
private UUID id;
private String name;
}
List<User> userList=new ArrayList<>();
for(Object[] data:matchedData){
userList.add(new User(UUID.fromString(String.valueOf(data[0])),
String.valueOf(data[1])));
}
假设这是我们拥有的实体
函数或过程 returning void 导致 JPA/Hibernate 出现问题,因此将其更改为 return integer 并在过程结束时调用 return 1 可能会解决问题。
SQL类型1111表示String。
另一个简单的解释可能是您正在获取复杂类型 (Entity/POJO) 但未指定要映射到的实体:
String sql = "select yourentity.* from {h-schema}Yourentity yourentity";
return entityManager.createNativeQuery(sql).getResultList();
只需在 createNativeQuery 方法中添加 class 映射到:
return entityManager.createNativeQuery(sql, Yourentity.class).getResultList();
在我的例子中,问题是 Hibernate 不知道如何处理 UUID
列。如果您使用的是 Postgres,请尝试将此添加到您的 resources/application.properties
:
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQL9Dialect
如果使用 Postgres
public class CustomPostgreSqlDialect extends PostgreSQL94Dialect{
@Override
public SqlTypeDescriptor remapSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor)
{
switch (sqlTypeDescriptor.getSqlType())
{
case Types.CLOB:
return VarcharTypeDescriptor.INSTANCE;
case Types.BLOB:
return VarcharTypeDescriptor.INSTANCE;
case 1111://1111 should be json of pgsql
return VarcharTypeDescriptor.INSTANCE;
}
return super.remapSqlTypeDescriptor(sqlTypeDescriptor);
}
public CustomPostgreSqlDialect() {
super();
registerHibernateType(1111, "string");
}}
并使用
<prop key="hibernate.dialect">com.abc.CustomPostgreSqlDialect</prop>
如果您正在调用 EntityManager.createNativeQuery(),请务必在第二个参数中包含结果 java class:
return em.createNativeQuery(sql, MyRecord.class).getResultList()
在尝试了许多建议的解决方案之后,包括:
终于是这个用最少的更改修复了所有问题:
https://gist.github.com/agrawald/adad25d28bf6c56a7e4618fe95ee5a39
诀窍是不要在 class 上有 @TypeDef
,而是在 2 个不同的 package-info.java
文件中有 2 个不同的 @TypeDef
。一个在生产代码包中用于生产数据库,一个在测试包中用于测试 H2 数据库。
我正在开发 Spring JPA 应用程序,使用 MySQL 作为数据库。我确保加载了所有 spring-jpa 库、hibernate 和 mysql-connector-java。
我是 运行 一个 mysql 5 实例。这是我的 application.properties 文件的摘录:
spring.jpa.show-sql=false
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.database-platform=org.hibernate.dialect.MySQL5Dialect
spring.datasource.url=jdbc:mysql://localhost/mydatabase
spring.datasource.username=myuser
spring.datasource.password=SUPERSECRET
spring.datasource.driverClassName=com.mysql.jdbc.Driver
执行集成测试时,spring 正常启动但无法创建休眠 SessionFactory,例外情况是:
org.hibernate.MappingException: No Dialect mapping for JDBC type: 1111
我认为我的方言应该是 Mysql5Dialect,我也尝试了明确说明 InnoDB 的方言,以及两个不指示版本 5 的方言选项。但我总是得到相同的 'No Dialect mapping for JDBC type: 1111' 消息. 我的 application.properties 文件位于 test/resources 源文件夹中。它被 JUnit 测试运行器识别(我之前因为其中的拼写错误而出现异常)。
是我设置的属性有误吗?我找不到关于这些 属性 名称的一些官方文档,但在这个 Whosebug 答案中找到了提示:
期待您的回答,谢谢!
顺便说一句,该应用程序已经在使用 spring 引导。
这里是基于 SubOptimal 的评论的答案:
错误信息实际上是说一个列类型不能被hibernate映射到一个数据库类型。
在我的例子中,它是我在我的一些实体中用作主键的 java.util.UUID
类型。只需应用注释 @Type(type="uuid-char")
(对于 postgres @Type(type="pg-uuid")
)
还有另一个常见的用例抛出此异常。调用 returns void
的函数。有关更多信息和解决方案,请转到 here.
有时当您调用 sql procedure/function 时,可能需要 return 一些东西。您可以尝试 returning void: RETURN;
或 string(这个对我有用):RETURN 'OK'
请检查某些列 return 中是否有许多 未知类型 在查询中。
例如:'1' as column_name 可以有未知类型
和1因为column_name是整数是正确的一.
这东西对我有用。
对于使用旧休眠 (3.x) 版本遇到此错误的任何人:
不要用大写字母写return类型。 hibernate 类型实现映射使用小写 return 类型并且不转换它们:
CREATE OR REPLACE FUNCTION do_something(param varchar)
RETURNS integer AS
$BODY$
...
在我的例子中,问题是我在我的用户 class 中设置存储过程时忘记添加 resultClasses 属性。
@NamedStoredProcedureQuery(name = "find_email",
procedureName = "find_email", resultClasses = User.class, //<--I forgot that.
parameters = {
@StoredProcedureParameter(mode = ParameterMode.IN, name = "param_email", type = String.class)
}),
我遇到了同样的错误,因为我的查询返回了一个 UUID 列。为了解决这个问题,我通过 "cast(columnName as varchar)" 之类的查询将 UUID 列作为 varchar 类型返回,然后它起作用了。
示例:
public interface StudRepository extends JpaRepository<Mark, UUID> {
@Modifying
@Query(value = "SELECT Cast(stuid as varchar) id, SUM(marks) as marks FROM studs where group by stuid", nativeQuery = true)
List<Student> findMarkGroupByStuid();
public static interface Student(){
private String getId();
private String getMarks();
}
}
当您使用 Hibernate 和 returning void 函数时也会发生这种情况。至少有 postgres。它不知道如何处理 void。我最终不得不将 void 更改为 return int.
如果您使用的是 Postgres,请检查您是否没有 Abstime 类型的列。 Abstime 是 JPA 无法识别的内部 Postgres 数据类型。在这种情况下,如果您的业务要求允许,使用 TO_CHAR 转换为文本可能 有所帮助。
如果您有原生 SQL 查询,则通过向查询添加转换来修复它。
例子:
CAST('yourString' AS varchar(50)) as anyColumnName
就我而言,它对我有用。
这是 Hibernate (5.x) 版本
正在调用数据库函数 return JSON string/object
为此使用 unwrap(org.hibernate.query.NativeQuery.class).addScalar()
相同的方法。
示例如下(Spring & 休眠):
@PersistenceContext
EntityManager em;
@Override
public String getJson(String strLayerName) {
String *nativeQuery* = "select fn_layer_attributes(:layername)";
return em.createNativeQuery(*nativeQuery*).setParameter("layername", strLayerName).**unwrap(org.hibernate.query.NativeQuery.class).addScalar**("fn_layer_attributes", **new JsonNodeBinaryType()**) .getSingleResult().toString();
}
查找触发问题的列
首先,您没有提供实体映射,因此我们无法判断是哪个列产生了这个问题。例如,它可以是 UUID
或 JSON
列。
现在,您使用的是非常古老的 Hibernate 方言。 MySQL5Dialect
适用于 MySQL 5。很可能您使用的是较新的 MySQL 版本。
因此,尝试使用 MySQL8Dialect
代替:
spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect
添加非标准类型
如果您因为使用 JSON 列类型而遇到问题,请尝试提供支持非标准类型的自定义 Hibernate 方言:
public class MySQL8JsonDialect
extends MySQL8Dialect{
public MySQL8JsonDialect() {
super();
this.registerHibernateType(
Types.OTHER, JsonStringType.class.getName()
);
}
}
答案使用自定义 Hibernate 方言:
<property
name="hibernate.dialect"
value="com.vladmihalcea.book.hpjp.hibernate.type.json.MySQL8JsonDialect"
/>
如果在执行 SQL 本地查询时出现此异常,则需要通过 addScalar
:
JsonNode properties = (JsonNode) entityManager
.createNativeQuery(
"SELECT properties " +
"FROM book " +
"WHERE isbn = :isbn")
.setParameter("isbn", "978-9730228236")
.unwrap(org.hibernate.query.NativeQuery.class)
.addScalar("properties", JsonStringType.INSTANCE)
.getSingleResult();
assertEquals(
"High-Performance Java Persistence",
properties.get("title").asText()
);
我得到了同样的错误,这里的问题是存储在数据库中的 UUID 没有转换为对象。
我尝试应用这些注释@Type(type="uuid-char")(对于 postgres @Type(type="pg-uuid")但它对我不起作用。
这对我有用。假设您想要来自 table 的 id 和 name 以及 JPA 中的本机查询。使用字段 id 和 name 创建一个实体 class,例如 'User',然后尝试将 object[] 转换为我们想要的实体。这里匹配的数据是我们从查询中获得的对象数组列表。
@Query( value = "SELECT CAST(id as varchar) id, name from users ", nativeQuery = true)
public List<Object[]> search();
public class User{
private UUID id;
private String name;
}
List<User> userList=new ArrayList<>();
for(Object[] data:matchedData){
userList.add(new User(UUID.fromString(String.valueOf(data[0])),
String.valueOf(data[1])));
}
假设这是我们拥有的实体
函数或过程 returning void 导致 JPA/Hibernate 出现问题,因此将其更改为 return integer 并在过程结束时调用 return 1 可能会解决问题。
SQL类型1111表示String。
另一个简单的解释可能是您正在获取复杂类型 (Entity/POJO) 但未指定要映射到的实体:
String sql = "select yourentity.* from {h-schema}Yourentity yourentity";
return entityManager.createNativeQuery(sql).getResultList();
只需在 createNativeQuery 方法中添加 class 映射到:
return entityManager.createNativeQuery(sql, Yourentity.class).getResultList();
在我的例子中,问题是 Hibernate 不知道如何处理 UUID
列。如果您使用的是 Postgres,请尝试将此添加到您的 resources/application.properties
:
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQL9Dialect
如果使用 Postgres
public class CustomPostgreSqlDialect extends PostgreSQL94Dialect{
@Override
public SqlTypeDescriptor remapSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor)
{
switch (sqlTypeDescriptor.getSqlType())
{
case Types.CLOB:
return VarcharTypeDescriptor.INSTANCE;
case Types.BLOB:
return VarcharTypeDescriptor.INSTANCE;
case 1111://1111 should be json of pgsql
return VarcharTypeDescriptor.INSTANCE;
}
return super.remapSqlTypeDescriptor(sqlTypeDescriptor);
}
public CustomPostgreSqlDialect() {
super();
registerHibernateType(1111, "string");
}}
并使用
<prop key="hibernate.dialect">com.abc.CustomPostgreSqlDialect</prop>
如果您正在调用 EntityManager.createNativeQuery(),请务必在第二个参数中包含结果 java class:
return em.createNativeQuery(sql, MyRecord.class).getResultList()
在尝试了许多建议的解决方案之后,包括:
终于是这个用最少的更改修复了所有问题:
https://gist.github.com/agrawald/adad25d28bf6c56a7e4618fe95ee5a39
诀窍是不要在 class 上有 @TypeDef
,而是在 2 个不同的 package-info.java
文件中有 2 个不同的 @TypeDef
。一个在生产代码包中用于生产数据库,一个在测试包中用于测试 H2 数据库。