0

For legacy reasons I have composite keys in my database, I use @IdClass to map them (before I used @Embeddedid but it had it's own bugs). However I have problem whenever I'm trying to save composite key entity that contains proxy as id field. I made very simple example to isolate this problem (example uses Spring Data, but I think its irrelevant). p.s. I know that calling .save is not necessary, but it should not cause exception.

@Entity
public class Image {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String fileName;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getFileName() {
        return fileName;
    }

    public void setFileName(String fileName) {
        this.fileName = fileName;
    }
}

@Entity
public class Product {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String name;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

@Entity
@IdClass(ProductImage.ProductImageId.class)
public class ProductImage {

    public static class ProductImageId implements Serializable {

        private static final long serialVersionUID = 8542391285589067304L;

        private Long product;

        private Long image;

        public ProductImageId() {
        }

        public Long getProduct() {
            return product;
        }

        public void setProduct(Long product) {
            this.product = product;
        }

        public Long getImage() {
            return image;
        }

        public void setImage(Long image) {
            this.image = image;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            ProductImageId that = (ProductImageId) o;
            return Objects.equals(product, that.product) &&
                    Objects.equals(image, that.image);
        }

        @Override
        public int hashCode() {
            return Objects.hash(product, image);
        }
    }

    @ManyToOne(fetch = FetchType.LAZY)
    @Id
    private Product product;

    @ManyToOne(fetch = FetchType.LAZY)
    @Id
    private Image image;

    private Integer number;

    public Product getProduct() {
        return product;
    }

    public void setProduct(Product product) {
        this.product = product;
    }

    public Image getImage() {
        return image;
    }

    public void setImage(Image image) {
        this.image = image;
    }

    public Integer getNumber() {
        return number;
    }

    public void setNumber(Integer number) {
        this.number = number;
    }
}

    List<ProductImage> productImages = productImageRepository.findAll();
    productImages.get(0).setNumber(456);
    productImageRepository.save(productImages.get(0));

Caused by: java.lang.IllegalArgumentException: Cannot convert value of type 'com.example.springbootnewplayground.Product$HibernateProxy$AJ38NiN6' to required type 'java.lang.Long' for property 'product': PropertyEditor [org.springframework.beans.propertyeditors.CustomNumberEditor] returned inappropriate value of type 'com.example.springbootnewplayground.Product$HibernateProxy$AJ38NiN6' at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:258) ~[spring-beans-5.1.6.RELEASE.jar:5.1.6.RELEASE] at org.springframework.beans.AbstractNestablePropertyAccessor.convertIfNecessary(AbstractNestablePropertyAccessor.java:585) ~[spring-beans-5.1.6.RELEASE.jar:5.1.6.RELEASE] ... 69 common frames omitted

  • It feels like you are experiencing the issue due too lazy loading . Have you tried to `unproxy` your object first as discussed here ? [Converting Hibernate proxy to a real entity object](https://stackoverflow.com/questions/2216547/converting-hibernate-proxy-to-a-real-entity-object) and here [how to unproxy a hibernate object](https://stackoverflow.com/questions/11228838/how-to-unproxy-a-hibernate-object) – anasmi Apr 12 '19 at 07:12
  • probably it will work If I will unproxy whole object structure, but in big project, with big nested structure of classes it will be very ugly. I also think its because of lazy initialization, but it seems like its bug, because at that point proxy still has access to entity manager and it can easily instantiate itself. – Luka Gorgadze Apr 12 '19 at 07:26
  • Its not bug, Spring applies transaction management at the repository level, so you will not have acces to your lazy properties outside repository level. https://stackoverflow.com/questions/25709976/spring-boot-spring-data-how-are-hibernate-sessions-managed/25710391#25710391 – Tijkijiki Apr 12 '19 at 12:10
  • Its same problem even if I use @Transactional annotation, I know as a fact that on the line where I get error, while debugging if I call methods of proxy entity, I get data and not lazy initialization error. – Luka Gorgadze Apr 12 '19 at 12:54

0 Answers0