'Exception trying convert UUID attribute (foreign key) to Entity object

I am developing a spring-boot application (jpa...etc), and I am stuck in one problem. I am using the UUID attribute for the primary keys. When I try to create object as foreign key, the jpa can't cast correctly to my object.

I tried to use a AttributeConverter, but jpa does not call it.

My UserEntity

@Entity(name = "User")
@Table(name = "USR")
@EntityListeners(UserPersistListener.class)
@EqualsAndHashCode
public class UserEntity {

    @Id
    @GeneratedValue(generator = "uuid2")
    @GenericGenerator(name = "uuid2", strategy = "uuid2")
    @Column(name = "ID", updatable = false)
    @Getter
    @Setter
    private String id;

    @Column(name = "LOGIN", updatable = false)
    @Getter
    @Setter
    private String login;

    @Column(name = "PASS")
    @Getter
    @Setter
    private String pass;

    @Enumerated(EnumType.STRING)
    @Column(name = "ROLE")
    @Getter
    @Setter
    private Role role;

}

My other Entity Person using UserEntity (foreign key)

@Entity(name = "Person")
@Table(name = "PERSON")
@EqualsAndHashCode
public class PersonEntity {

    @Id
    @GeneratedValue(generator = "uuid2")
    @GenericGenerator(name = "uuid2", strategy = "uuid2")
    @Column(name = "ID", updatable = false)
    @Getter
    @Setter
    private String id;

    @Column(name = "NAME")
    @Getter
    @Setter
    private String name;

    @Column(name = "SUBSCRIPTION")
    @Getter
    @Setter
    private Long subscription;

    @Enumerated(EnumType.STRING)
    @Column(name = "SUBSCRIPTION_TYPE")
    @Getter
    @Setter
    private SubscriptionType subscriptionType;

    @Column(name = "PHONE1")
    @Getter
    @Setter
    private Long phone1;

    @Column(name = "PHONE2")
    @Getter
    @Setter
    private Long phone2;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "CREATED_BY", updatable = false)
    @Getter
    @Setter
    private UserEntity createdBy;

    @Convert(converter = LocalDateAttributeConverter.class)
    @Column(name = "CREATION_DATE")
    @Getter
    @Setter
    private LocalDateTime creationDate;

}

Exception

org.springframework.data.domain.PageImpl["content"]->java.util.Collections$UnmodifiableRandomAccessList[0]->br.com.orangesun.entity.person.PersonEntity["createdBy"]->br.com.orangesun.entity.user.UserEntity_$$_jvst424_1["id"])
2019-06-18 00:52:55.163  WARN 15432 --- [nio-8099-exec-9] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Error: 0, SQLState: 42883
2019-06-18 00:52:55.164 ERROR 15432 --- [nio-8099-exec-9] o.h.engine.jdbc.spi.SqlExceptionHelper   : ERROR: operator does not exist: uuid = character varying
  Hint: No operator matches the given name and argument types. You might need to add explicit type casts.

Edit

My database definition

| Field Name        | Type    |
|-----------------------------|
| id                | uuid    |
| name              | varchar |
| subscription      | int8    |
| subscription_type | varchar |
| created_by        | uuid    |
| creation_date     | instant |
| phone1            | int8    |
| phone2            | int8    |
|-----------------------------|

EDIT 2

Other details about same error

java.lang.IllegalArgumentException: Provided id of the wrong type for class br.com.orangesun.entity.person.PersonEntity. Expected: class java.lang.String, got class java.util.UUID


Solution 1:[1]

Try to use UUID type instead of String for 'id' fields, because UUID is a binary format, not character based, so databases use special type for UUID fields.

Solution 2:[2]

Update your PersonEntity class as below,

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "CREATED_BY", referencedColumnName = "ID”, updatable = false)
@Getter
@Setter
private UserEntity createdBy;

Add referencedColumnName to your @joinColumn

Solution 3:[3]

UUID in Postgres is automatically converted for you into UUID datatype. You must change your id datatype from String to UUID and everything will work as expected.

@Id
@GeneratedValue(generator = "uuid2")
@GenericGenerator(name = "uuid2", strategy = "uuid2")
@Column(name = "ID", updatable = false)
@Getter
@Setter
private UUID id;

Solution 4:[4]

Use UUID instead of String.

Moreover, replace

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "CREATED_BY", updatable = false)

by

@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "CREATED_BY", referencedColumnName = "ID", updatable = false)

It gives:

The UserEntity:

@Entity(name = "User")
@Table(name = "USR")
@EntityListeners(UserPersistListener.class)
@EqualsAndHashCode
public class UserEntity {

    @Id
    @GeneratedValue(generator = "uuid2")
    @GenericGenerator(name = "uuid2", strategy = "uuid2")
    @Column(name = "ID", updatable = false)
    @Getter
    @Setter
    private UUID id;

    @Column(name = "LOGIN", updatable = false)
    @Getter
    @Setter
    private String login;

    @Column(name = "PASS")
    @Getter
    @Setter
    private String pass;

    @Enumerated(EnumType.STRING)
    @Column(name = "ROLE")
    @Getter
    @Setter
    private Role role;

}

The other Entity Person using UserEntity (foreign key)

@Entity(name = "Person")
@Table(name = "PERSON")
@EqualsAndHashCode
public class PersonEntity {

    @Id
    @GeneratedValue(generator = "uuid2")
    @GenericGenerator(name = "uuid2", strategy = "uuid2")
    @Column(name = "ID", updatable = false)
    @Getter
    @Setter
    private UUID id;

    @Column(name = "NAME")
    @Getter
    @Setter
    private String name;

    @Column(name = "SUBSCRIPTION")
    @Getter
    @Setter
    private Long subscription;

    @Enumerated(EnumType.STRING)
    @Column(name = "SUBSCRIPTION_TYPE")
    @Getter
    @Setter
    private SubscriptionType subscriptionType;

    @Column(name = "PHONE1")
    @Getter
    @Setter
    private Long phone1;

    @Column(name = "PHONE2")
    @Getter
    @Setter
    private Long phone2;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "CREATED_BY", referencedColumnName = "ID", updatable = false)
    @Getter
    @Setter
    private UserEntity createdBy;

    @Convert(converter = LocalDateAttributeConverter.class)
    @Column(name = "CREATION_DATE")
    @Getter
    @Setter
    private LocalDateTime creationDate;

}

as per OP gmrosa's own prior edit to the question.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Ivan Rasikhin
Solution 2 Tarun Jain
Solution 3 Alan Sereb
Solution 4 vinzee