No Dialect mapping for JDBC type: 1111
Asked Answered
N

23

64

I'm working on a Spring JPA Application, using MySQL as database. I ensured that all spring-jpa libraries, hibernate and mysql-connector-java is loaded.

I'm running a mysql 5 instance. Here is a excerpt of my application.properties file:

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

When executing an integration test, spring startsup properly but fails on creating the hibernate SessionFactory, with the exception:

org.hibernate.MappingException: No Dialect mapping for JDBC type: 1111

I think my dialects should be Mysql5Dialect, I also tried the one explicitly stating InnoDB, and the two dialect options which don't indicate the version 5. But I always end up with the same 'No Dialect mapping for JDBC type: 1111' message. My application.properties file resides in the test/resources source folder. It is recognized by the JUnit Test runner (I previously got an exception because of an typo in it).

Are the properties I'm setting wrong? I couldn't find some official documentation on these property names but found a hint in this stackoverflow answer: https://mcmap.net/q/302895/-connect-mysql-to-spring-application

Looking forward for your answers, thanks!

BTW The application is already using spring boot.

Nonbelligerent answered 28/1, 2015 at 12:42 Comment(4)
The error message means one column returns data in a type which cannot be mapped. No Dialect mapping for JDBC type: 1111 indicates java.sql.Types.OTHER`. What column types do you select from the table?Lucindalucine
Oh, thanks. I thought this means the dialect type ... Yeah I like to use UUIDs as IDs and we previously always worked with postgres, which has a UUID column type. So we could just say @Type(type="pg-uuid"); I don't think mysql has an UUID column type thoughNonbelligerent
Just found out it is very similar to postgres: apply @Type(type="uuid-char") annotation to the id attribute.Nonbelligerent
I have this problem if put on SELECT statement a json field. I use PostgresSQL and a custom hibernate field Type for json type.Frear
N
37

Here the answer based on the comment from SubOptimal:

The error message actually says that one column type cannot be mapped to a database type by hibernate. In my case it was the java.util.UUID type I use as primary key in some of my entities. Just apply the annotation @Type(type="uuid-char") (for postgres @Type(type="pg-uuid"))

Nonbelligerent answered 28/1, 2015 at 13:9 Comment(3)
If you get the exception only in test environment on HSQLDB - take a look at #1007676Implosion
I agree with Lu55 . You should not add the @Type annotation until it is really necessary. But I don't really agree with the solutions provided in the linked issue (maybe they are just too old?). Therefore I create a post with my own solution: #1007676Creamcolored
Or alternatively in your query string you can also do a Casting to Varchar like so: CAST( table_name.column_name as VARCHAR) AS table_nameStephaniastephanie
B
50

I got the same error because my query returned a UUID column. To fix that I returned the UUID column as varchar type through the query like "cast(columnName as varchar)", then it worked.

Example:

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();
    }
}
Bookkeeping answered 3/1, 2019 at 6:16 Comment(0)
N
37

Here the answer based on the comment from SubOptimal:

The error message actually says that one column type cannot be mapped to a database type by hibernate. In my case it was the java.util.UUID type I use as primary key in some of my entities. Just apply the annotation @Type(type="uuid-char") (for postgres @Type(type="pg-uuid"))

Nonbelligerent answered 28/1, 2015 at 13:9 Comment(3)
If you get the exception only in test environment on HSQLDB - take a look at #1007676Implosion
I agree with Lu55 . You should not add the @Type annotation until it is really necessary. But I don't really agree with the solutions provided in the linked issue (maybe they are just too old?). Therefore I create a post with my own solution: #1007676Creamcolored
Or alternatively in your query string you can also do a Casting to Varchar like so: CAST( table_name.column_name as VARCHAR) AS table_nameStephaniastephanie
P
22

There is also another common use-case throwing this exception. Calling function which returns void. For more info and solution go here.

Parthen answered 31/5, 2015 at 19:59 Comment(0)
U
13

I got the same error, the problem here is UUID stored in DB is not converting to object.

I tried applying these annotations @Type(type="uuid-char") (for postgres @Type(type="pg-uuid") but it didn't work for me.

This worked for me. Suppose you want id and name from a table with a native query in JPA. Create one entity class like 'User' with fields id and name and then try converting object[] to entity we want. Here this matched data is list of array of object we are getting from query.

@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])));

    }

Suppose this is the entity we have

Underscore answered 5/4, 2020 at 22:53 Comment(1)
Thanks, works. Why is UUID not converted into anything? Is it supposed to be that way or is it a bug?Houle
E
11

Please Check if some Column return many have unknow Type in Query .

eg : '1' as column_name can have type unknown

and 1 as column_name is Integer is correct One .

This thing worked for me.

Epigastrium answered 5/12, 2016 at 12:0 Comment(2)
I had a native query with a my own SqlResultMapping and this was the problem, fixed it by adding a cast to the query ''CAST('staticstring' AS varchar(50)) as columnmappingnamePitta
Yes, you have to use this CAST function within your QUERY to typecast into your appropriate DataType.Epigastrium
C
10

Finding the column that triggered the issue

First, you didn't provide the entity mapping so that we could tell what column generated this problem. For instance, it could be a UUID or a JSON column.

Now, you are using a very old Hibernate Dialect. The MySQL5Dialect is meant for MySQL 5. Most likely you are using a newer MySQL version.

So, try to use the MySQL8Dialect instead:

spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect

Adding non-standard types

In case you got the issue because you are using a JSON column type, try to provide a custom Hibernate Dialect that supports the non-standard Type:

public class MySQL8JsonDialect
        extends MySQL8Dialect{
 
    public MySQL8JsonDialect() {
        super();
        this.registerHibernateType(
            Types.OTHER, JsonStringType.class.getName()
        );
    }
}

And use the custom Hibernate Dialect:

<property
    name="hibernate.dialect"
    value="com.vladmihalcea.book.hpjp.hibernate.type.json.MySQL8JsonDialect"
/>

If you get this exception when executing SQL native queries, then you need to pass the type via 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()
);
Chorus answered 15/1, 2020 at 15:26 Comment(3)
Adding dialect didn't help, unfortunately only Unit test build is failing in my case. (UT has local db) @Vlad MihalceaSocket
As long as you run the integration tests on MySQL in a Docker container, everything will work like a charm. If you use in-memory DBs, like H2 or HSQLDB, it will not work.Chorus
Ya using, in memory db here, got past that error, now facing another. Caused by: org.hibernate.exception.SQLGrammarException: could not prepare statement Will try to fix this too.Socket
P
4

If you have native SQL query then fix it by adding a cast to the query.

Example:

CAST('yourString' AS varchar(50)) as anyColumnName

In my case it worked for me.

Peta answered 9/10, 2019 at 11:52 Comment(0)
M
3

Sometimes when you call sql procedure/function it might be required to return something. You can try returning void: RETURN; or string (this one worked for me): RETURN 'OK'

Misdate answered 8/9, 2015 at 11:56 Comment(1)
RETURN 1 will be quick I guess.Girdle
A
3

Another simple explanation might be that you're fetching a complex Type (Entity/POJO) but do not specify the Entity to map to:

String sql = "select yourentity.* from {h-schema}Yourentity yourentity";
return entityManager.createNativeQuery(sql).getResultList();

simply add the class to map to in the createNativeQuery method:

return entityManager.createNativeQuery(sql, Yourentity.class).getResultList();
Acuate answered 26/2, 2021 at 9:14 Comment(0)
V
3

In my case, the issue was Hibernate not knowing how to deal with an UUID column. If you are using Postgres, try adding this to your resources/application.properties:

spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQL9Dialect
Viperous answered 24/3, 2021 at 8:35 Comment(0)
J
1

In my case the problem was that, I forgot to add resultClasses attribute when I setup my stored procedure in my User class.

@NamedStoredProcedureQuery(name = "find_email",
                procedureName = "find_email", resultClasses = User.class, //<--I forgot that. 
                parameters = {
                    @StoredProcedureParameter(mode = ParameterMode.IN, name = "param_email", type = String.class)
                }),
Jackass answered 26/3, 2018 at 11:51 Comment(0)
S
1

This also happens when you are using Hibernate and returning a void function. AT least w/ postgres. It doesnt know how to handle the void. I ended up having to change my void to a return int.

Seidler answered 4/7, 2019 at 15:27 Comment(0)
V
1

If you are using Postgres, check that you don't have a column of type Abstime. Abstime is an internal Postgres datatype not recognized by JPA. In this case, converting to Text using TO_CHAR could help if permitted by your business requirements.

Vicinage answered 1/8, 2019 at 13:31 Comment(1)
im facing the same problem as mentioned here. is there an other solution yet? it keeps me from doing asterisk queries.Depolymerize
G
1

if using 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");
    }}

and use

<prop key="hibernate.dialect">com.abc.CustomPostgreSqlDialect</prop>
Grist answered 6/4, 2021 at 13:3 Comment(1)
And if you are using spring, instead of the hibernate.dialect prop mentioned, at the properties file put: spring.jpa.properties.hibernate.dialect=com.abc.CustomPostgreSqlDialectZinc
R
0

For anybody getting this error with an old hibernate (3.x) version:

do not write the return type in capital letters. hibernate type implementation mapping uses lowercase return types and does not convert them:

CREATE OR REPLACE FUNCTION do_something(param varchar)
    RETURNS integer AS
$BODY$
...
Rondel answered 18/1, 2018 at 10:6 Comment(0)
V
0

This is for Hibernate (5.x) version

Calling database function which return JSON string/object

For this use unwrap(org.hibernate.query.NativeQuery.class).addScalar() methods for the same.

Example as below (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();

    }

Voe answered 15/10, 2019 at 9:46 Comment(0)
J
0

Function or procedure returning void cause some issue with JPA/Hibernate, so changing it with return integer and calling return 1 at the end of procedure may solved the problem.

SQL Type 1111 represents String.

Jalisajalisco answered 19/9, 2020 at 12:6 Comment(0)
W
0

If you are calling EntityManager.createNativeQuery(), be sure to include the resulting java class in the second parameter:

return em.createNativeQuery(sql, MyRecord.class).getResultList()
Watercolor answered 11/3, 2022 at 16:26 Comment(0)
M
0

After trying many proposed solutions, including:

it was finally this one that fixed everything with the least amount of changes:

https://gist.github.com/agrawald/adad25d28bf6c56a7e4618fe95ee5a39

The trick is to not have @TypeDef on your class, but instead have 2 different @TypeDef in 2 different package-info.java files. One inside your production code package for your production DB, and one inside your test package for your test H2 DB.

Melodramatic answered 28/4, 2022 at 10:48 Comment(1)
@VladMihalcea according to the last comment in gist.github.com/agrawald/adad25d28bf6c56a7e4618fe95ee5a39 I shouldn't need this fix when using your JsonType. However, I was already using your JsonType (for PostGIS in Production and H2 in my @SpringDataTests), and only the above solution was able to fix it for me.Melodramatic
L
0

I had the same issue and wasted like 1 hour before I noticed that I use JpaRepository of one entity (let's say Person) to retrive another entity (let's say Order). Hope this helps someone.

Lumpfish answered 27/4, 2023 at 14:55 Comment(0)
V
0

I had little different issue, I was facing this issue for pagination. When select query was pulling number of records (15) more than pageSize(10) then I was getting below error. -

Details: org.springframework.orm.jpa.JpaSystemException: No Dialect mapping for JDBC type: 1111; nested exception is org.hibernate.MappingException: No Dialect mapping for JDBC type: 1111

Before fixing I made sure -

  1. My Dialect lib is latest
  2. column data types are correct

Fix - added registerHibernateType

@Component
public class JSONBPostgreSQLDialect extends PostgreSQL95Dialect {

    public JSONBPostgreSQLDialect() {
        super();
        registerColumnType(Types.JAVA_OBJECT, JSONBUserType.JSONB_TYPE);
        //This line fixed Dialect mapping errorx
        registerHibernateType(Types.OTHER, String.class.getName());
    }
}

JSONBUserType is custom type created.

@Component
public class JSONBUserType implements UserType, ParameterizedType {

    private static final ClassLoaderService classLoaderService = new ClassLoaderServiceImpl();

    public static final String JSONB_TYPE = "jsonb";
    public static final String CLASS = "CLASS";

    private Class jsonClassType;

    @Override
    public Class<Object> returnedClass() {
        return Object.class;
    }

    @Override
    public int[] sqlTypes() {
        return new int[]{Types.JAVA_OBJECT};
    }

    @Override
    public Object nullSafeGet(ResultSet rs,
                              String[] names,
                              SharedSessionContractImplementor session,
                              Object owner)
            throws HibernateException, SQLException {

        final String cellContent = rs.getString(names[0]);
        if (cellContent == null) {
            return null;
        }
        try {
            final ObjectMapper mapper = new ObjectMapper();
            return mapper.readValue(cellContent.getBytes("UTF-8"), jsonClassType);
        } catch (final Exception ex) {
            throw new RuntimeException("Failed to convert String to Invoice: " + ex.getMessage(), ex);
        }
    }

    @Override
    public void nullSafeSet(PreparedStatement ps,
                            Object value,
                            int idx,
                            SharedSessionContractImplementor session)
            throws HibernateException, SQLException {
        if (value == null) {
            ps.setNull(idx,
                       Types.OTHER);
            return;
        }
        try {
            final ObjectMapper mapper = new ObjectMapper();
            final StringWriter w = new StringWriter();
            mapper.writeValue(w,
                              value);
            w.flush();
            ps.setObject(idx,
                         w.toString(),
                         Types.OTHER);
        } catch (final Exception ex) {
            throw new RuntimeException("Failed to convert Invoice to String: " + ex.getMessage(),
                                       ex);
        }

    }

    @Override
    public void setParameterValues(Properties parameters) {
        final String clazz = (String) parameters.get(CLASS);
        if (null != clazz) {
            jsonClassType = classLoaderService.classForName(clazz);
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    public Object deepCopy(Object value) throws HibernateException {

        if (!(value instanceof Collection)) {
            return value;
        }

        Collection<?> collection = (Collection) value;
        Collection collectionClone = CollectionFactory.newInstance(collection.getClass());

        collectionClone.addAll(collection.stream()
                                         .map(this::deepCopy)
                                         .collect(Collectors.toList()));

        return collectionClone;
    }

    static final class CollectionFactory {
        @SuppressWarnings("unchecked")
        static <E, T extends Collection<E>> T newInstance(Class<T> collectionClass) {
            if (List.class.isAssignableFrom(collectionClass)) {
                return (T) new ArrayList<E>();
            } else if (Set.class.isAssignableFrom(collectionClass)) {
                return (T) new HashSet<E>();
            } else {
                throw new IllegalArgumentException("Unsupported collection type : " + collectionClass);
            }
        }
    }

    @Override
    public boolean isMutable() {
        return true;
    }

    @Override
    public boolean equals(Object x,
                          Object y) throws HibernateException {
        if (x == y) {
            return true;
        }

        if ((x == null) || (y == null)) {
            return false;
        }

        return x.equals(y);
    }

    @Override
    public int hashCode(Object x) throws HibernateException {
        assert (x != null);
        return x.hashCode();
    }

    @Override
    public Object assemble(Serializable cached,
                           Object owner) throws HibernateException {
        return deepCopy(cached);
    }

    @Override
    public Serializable disassemble(Object value) throws HibernateException {
        Object deepCopy = deepCopy(value);

        if (!(deepCopy instanceof Serializable)) {
            throw new SerializationException(String.format("%s is not serializable class",
                                                           value),
                                             null);
        }

        return (Serializable) deepCopy;
    }

    @Override
    public Object replace(Object original,
                          Object target,
                          Object owner) throws HibernateException {
        return deepCopy(original);
    }
}

And it is used in entity like this

@TypeDef(name = "addressValType", typeClass = JSONBUserType.class, parameters = {@Parameter(name = JSONBUserType.CLASS, value = "com.address.response.AddressResponse")})
@Table(name = "addressValidation")
public class Address implements Serializable {
    private static final long serialVersionUID = -2370572023911224797L;
    @Id
    @Column(name = "employeeNumber")
    private Integer employeeNumber;

    @Column(name = "inputAddress", columnDefinition = "jsonb")
    @Type(type = "addressValType")
    private SapPostalAddressResponse inputAddress;
  }
Valerlan answered 16/5, 2023 at 20:22 Comment(0)
B
0

you can solve this issue: "No Dialect mapping for JDBC type: xxx" in 3 steps

1.- Cast as text in query

SELECT CAST(my_column as text) From my_table;

2.- Create a custom AttributeConverter thats convert from text to your desired type, in this example String to integer[]

import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
import java.util.Arrays;
import java.util.stream.Collectors;

@Converter(autoApply = true)
public class IntegerArrayConverter implements AttributeConverter<Integer[], String> {

private static final String ARRAY_DELIMITER = ",";

@Override
public String convertToDatabaseColumn(Integer[] attribute) {
    System.out.println("convertToDatabaseColumn attribute: " + attribute);
    if (attribute == null || attribute.length == 0) {
        return null;
    }
    return Arrays.stream(attribute)
            .map(String::valueOf)
            .collect(Collectors.joining(ARRAY_DELIMITER));
}

@Override
public Integer[] convertToEntityAttribute(String dbData) {
    System.out.println("convertToEntityAttribute dbData: " + dbData);
    if (dbData == null || dbData.isEmpty()) {
        return null;
    }
    if(dbData.startsWith("{") && dbData.endsWith("}")) {
        dbData = dbData.substring(1, dbData.length() - 1);
    }
    String[] stringArray = dbData.split(ARRAY_DELIMITER);
    return Arrays.stream(stringArray)
            .map(Integer::parseInt)
            .toArray(Integer[]::new);
}
}

3.- Use convert in you entity like this:

@Convert(converter = IntegerArrayConverter.class)
@Column(name = "my_column", columnDefinition = "integer[]")
private Integer[] MyColumn;
Bruno answered 22/12, 2023 at 14:53 Comment(0)
J
0

In case of nativeQuery = true

A typical error after you copy-pasted a "second" (say) MyBRepository.java from the first one is: No Dialect mapping for JDBC type: 1111. It mean Hibernate cannot create a row object of your (say) MyEntityB return type. This happens when you mix the type you put into extends CrudRepository<MyEntityA, MyId> up.

So, double-check if the Template class fits the table you use in the native query. It

                                           // If this (A) type is wrong, then...
interface MyRepositoryA extends CrudRepository<MyEntityA, MyKey> {

  @Query(
      value       = "SELECT * FROM my_table_B mta WHERE ..."
      nativeQuery = true)
  List<MyEntityB> findManyB(List<UUID> refereceIds);
  // ... then you will get 'JDBC type: 1111' exception here, near to (B) return type.

To fix it

// replace
   extends CrudRepository<MyEntityA, ...
// with
   extends CrudRepository<MyEntityB, ...
Justinejustinian answered 26/4 at 11:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.