0

I have this weird conversion that should be handled automatically by hibernate and JPA, where it tries to map everything to varchar. I am using Spring boot from jhipster as base.

wrong column type encountered in column [height] in table [user]; found [decimal (Types#DECIMAL)], but expecting [varchar(255) (Types#VARCHAR)]

Entity example:

import javax.persistence.Entity;
import javax.persistence.Column;
import javax.persistence.Id;
import javax.persistence.Table;


@Entity
@Table(name = "user")
public class User extends AbstractAuditingEntity implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @Column(name = "id")
    @NotNull
    @Size(max = 36)
    private String id;

    @Column(name = "height")
    private BigDecimal height;

For liquibase the field is

<column name="height" type="number(3,2)"/>

What am I doing wrong that I have to add columnDefinition = "DECIMAL"? I have never had to do it manually. It also happens with Boolean entity to boolean DB or all date/timestamp types. I always have to add columnDefition property to column field.

I am guessing there is a converter that is not doing its job and I have misconfigured it?

DarkFeud
  • 181
  • 2
  • 16

1 Answers1

0

First guess: maybe you could change your liquibase field to the format described here

<column name="height" type="DECIMAL(3,2)"/>

If it does not work, what I suspect here is that BigDecimal needs a special conversion from and to number. It does not have an automatic conversion from and to primitive numbers in Java.

You may need a converter for BigDecimal to String to achieve this, as explained here.

@Converter
public class BigDecimalConverter implements AttributeConverter<BigDecimal, Long> {

  @Override
  public Long convertToDatabaseColumn(BigDecimal value) {
    if (value == null) {
        return null;
    } else {
        return value.multiply(BigDecimal.valueOf(100)).longValue();
    }
  }

  @Override
  public BigDecimal convertToEntityAttribute(Long value) {
    if (value == null) {
        return null;
    } else {
        return new BigDecimal(value).divide(BigDecimal.valueOf(100));
    }
  }
}

and then you can use the converter in your entitie's attributes:

@Convert(converter = BigDecimalConverter.class)
@Column(name = "height")
private BigDecimal height;
D-FENS
  • 1,438
  • 8
  • 21
  • Hmm, I have done these things in the past ( have not been coding for some years), but then I read that JPA is able to do this automatically. BigDecimal is different, but with dates for example https://in.relation.to/2018/02/20/java8-date-time-mapping/ – DarkFeud Dec 05 '21 at 10:46
  • Can you try first and change the column description to DECIMAL? – D-FENS Dec 05 '21 at 10:47
  • 1
    That works for JPA yes! By the way huge thanks for the help. I have in previous projects (some years back) never used columnDescription manually, it has always worked, but may be back then I was unaware of some configuration. i put it like this @Column(name = "height", columnDefinition = "DECIMAL") private BigDecimal height; – DarkFeud Dec 05 '21 at 10:54
  • Yeah, I usually leave stuff implicit and let JPA do the work, unless I need a specific change. The more configuration one has, the more potential of unintended consequences. – D-FENS Dec 05 '21 at 10:58
  • For dates, from Instant in Entity to Timestamp in DB, what would be responsible for the conversion. Do you have any ideas where I could have manually gone wrong that this automatic conversion is not happening? – DarkFeud Dec 05 '21 at 11:00
  • 1
    I think it is not supported and you would need an explicit convertor like the one above. More on that [here](https://stackoverflow.com/questions/49309076/why-jpa-does-not-support-java-time-instant). – D-FENS Dec 05 '21 at 11:05