[英]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 正常启动,但创建 hibernate SessionFactory 失败,异常:
org.hibernate.MappingException: No Dialect mapping for JDBC type: 1111
我认为我的方言应该是 Mysql5Dialect,我还尝试了一个明确说明 InnoDB 的方言,以及两个不指示版本 5 的方言选项。但我总是以相同的“JDBC 类型没有方言映射:1111”消息结束. 我的 application.properties 文件位于 test/resources 源文件夹中。 它被 JUnit 测试运行器识别(我之前因为其中的拼写错误而出现异常)。
我设置的属性有误吗? 我找不到关于这些属性名称的一些官方文档,但在这个 stackoverflow 答案中找到了提示: https://stackoverflow.com/a/25941616/1735497
期待您的解答,谢谢!
顺便说一句,该应用程序已经在使用 spring 启动。
我遇到了同样的错误,因为我的查询返回了一个 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();
}
}
这里的答案基于来自 SubOptimal 的评论:
错误消息实际上是说一种列类型无法通过休眠映射到数据库类型。 就我而言,它是我在某些实体中用作主键的java.util.UUID
类型。 只需应用注释@Type(type="uuid-char")
(对于 postgres @Type(type="pg-uuid")
)
还有另一个常见用例会引发此异常。 调用返回void
函数。 有关更多信息和解决方案,请访问此处。
请检查某些列是否返回许多未知类型的查询。
例如:“1”作为 column_name可以具有类型未知
和1 作为 column_name 是 Integer是正确的 One 。
这件事对我有用。
我遇到了同样的错误,这里的问题是存储在 DB 中的 UUID 没有转换为对象。
我尝试应用这些注释 @Type(type="uuid-char") (对于 postgres @Type(type="pg-uuid") 但它对我不起作用。
这对我有用。 假设您希望使用 JPA 中的本机查询从表中获取 id 和 name。 使用字段 id 和 name 创建一个像“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])));
}
假设这是我们拥有的实体
首先,您没有提供实体映射,以便我们可以判断是哪个列产生了这个问题。 例如,它可以是UUID
或JSON
列。
现在,您正在使用一种非常古老的 Hibernate 方言。 MySQL5Dialect
适用于 MySQL 5。很可能您使用的是较新的 MySQL 版本。
因此,尝试改用MySQL8Dialect
:
spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect
如果您因为使用 JSON 列类型而遇到问题,请尝试提供支持非标准类型的自定义 Hibernate Dialect:
public class MySQL8JsonDialect
extends MySQL8Dialect{
public MySQL8JsonDialect() {
super();
this.registerHibernateType(
Types.OTHER, JsonStringType.class.getName()
);
}
}
Ans 使用自定义 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()
);
有时,当您调用 sql 过程/函数时,可能需要返回某些内容。 您可以尝试返回 void: RETURN;
或字符串(这个对我RETURN 'OK'
): RETURN 'OK'
如果您有本机 SQL 查询,则通过向查询添加强制转换来修复它。
示例:
CAST('yourString' AS varchar(50)) as anyColumnName
就我而言,它对我有用。
就我而言,问题是,当我在 User 类中设置存储过程时,我忘记添加 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)
}),
当您使用 Hibernate 并返回 void 函数时,也会发生这种情况。 至少带有 postgres。 它不知道如何处理虚空。 我最终不得不将我的 void 改为 return int。
如果您使用 Postgres,请检查您是否没有Abstime类型的列。 Abstime 是 JPA 无法识别的内部 Postgres 数据类型。 在这种情况下,如果您的业务需求允许,使用TO_CHAR转换为文本可能会有所帮助。
另一个简单的解释可能是您正在获取复杂类型(实体/POJO)但未指定要映射到的实体:
String sql = "select yourentity.* from {h-schema}Yourentity yourentity";
return entityManager.createNativeQuery(sql).getResultList();
只需在 createNativeQuery 方法中添加要映射到的类:
return entityManager.createNativeQuery(sql, Yourentity.class).getResultList();
就我而言,问题是 Hibernate 不知道如何处理UUID
列。 如果您使用 Postgres,请尝试将其添加到您的resources/application.properties
:
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQL9Dialect
对于使用旧的休眠 (3.x) 版本遇到此错误的任何人:
不要用大写字母写返回类型。 hibernate 类型实现映射使用小写返回类型并且不转换它们:
CREATE OR REPLACE FUNCTION do_something(param varchar)
RETURNS integer AS
$BODY$
...
这是 Hibernate (5.x) 版本
调用返回 JSON 字符串/对象的数据库函数
为此,请使用unwrap(org.hibernate.query.NativeQuery.class).addScalar()
方法。
示例如下(Spring 和 Hibernate):
@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();
}
返回void 的函数或过程会导致 JPA/Hibernate 出现一些问题,因此使用 return integer更改它并在过程结束时调用 return 1 可能会解决问题。
SQL 类型 1111 表示字符串。
如果使用 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>
在我的情况下,它是通过添加 columnDefinition 解决的:
@Column(columnDefinition = "json")
如果您正在调用 EntityManager.createNativeQuery(),请务必在第二个参数中包含生成的 java class:
return em.createNativeQuery(sql, MyRecord.class).getResultList()
在尝试了许多建议的解决方案之后,包括:
最终是这个以最少的更改修复了所有问题:
https://gist.github.com/agrawald/adad25d28bf6c56a7e4618fe95ee5a39
诀窍是不要在您的@TypeDef
上使用@TypeDef
,而是在 2 个不同package-info.java
文件中使用 2 个不同的 @TypeDef。 一个在您的生产代码 package 中用于您的生产数据库,一个在您的测试代码 package 中用于您的测试 H2 数据库。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.