繁体   English   中英

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 正常启动,但创建 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])));

    }

假设这是我们拥有的实体

查找触发问题的列

首先,您没有提供实体映射,以便我们可以判断是哪个列产生了这个问题。 例如,它可以是UUIDJSON列。

现在,您正在使用一种非常古老的 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM