Unidirectional @OneToOne with reverse foreign key

We would like to create a unidirectional mapping @OneToOne

with a foreign key that is not in the main table but in the subordinate one. By providing the following java code, Hibernate tries to find the column product_ID

in the table product

, but not in the productimage

. Is it possible to make it work with single annotation modifications?

All unnecessary fields and columns have been removed from the example.

JPA Objects:

@Entity
public class Product {

    @Id
    @Column(name = "ID", unique = true)
    private String id;

    // this doesn't work
    @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
    @JoinColumn(name = "product_ID", nullable = false)
    private ProductImage productImage;

    // this works, but we want one-to-one
    // @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
    // @JoinColumn(name = "product_ID", nullable = false)
    // private List<ProductImage> productImages;

    // getters/setters omitted
}

@Entity
public class ProductImage {

    @Id
    @Column(name = "ID", unique = true)
    private String id;

    @Column
    @Lob
    private Blob data;

    // getters/setters omitted
}

      

Database tables:

CREATE TABLE `product` (
  `ID` varchar(255) NOT NULL,
  PRIMARY KEY (`ID`)
)

CREATE TABLE `productimage` (
  `ID` varchar(255) NOT NULL,
  `data` longblob NOT NULL,
  `product_ID` varchar(255) NOT NULL,
  PRIMARY KEY (`ID`),
  KEY `FK_123` (`product_ID`),
  CONSTRAINT `FK_123` FOREIGN KEY (`product_ID`) REFERENCES `product` (`ID`)
)

      

+6


source to share


4 answers


@OneToOne is a little misleading. This is most likely different from what you want. A classic one-to-one relationship database is modeled using the @ManyToOne JPA annotation in most cases. Try it. Never had problems with unidirectional relationships via @ManyToOne and @JoinColumn. I would also explicitly specify the productId field in the second class.



+1


source


Whether you map it as @OneToOne or @OneToMany, really neither here nor there: clients can only use what you show, so map it as @OneToMany and hide the implementation.

@Entity
public class Product {

    @Id
    @Column(name = "ID", unique = true)
    private String id;

    @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
    @JoinColumn(name = "product_ID", nullable = false)
    private List<ProductImage> productImages;

    //no getters or setters for productImages;

    public ProductImage getProductImage(){
         return productImages.size() > 0 ? productImages.get(0) : null;
    }
}

      



I also don't see any particular problem with making bidirectional communication as either 1-2-1 or 1-2-M. Again, don't expose the link from ProductImage> Product unless you want it to be publicly available.

0


source


It is a one-to-one inverse relationship. In a normal (not inverted) relationship, the source object stores a pointer (a column in the table) to the target object. But otherwise, the target object has a pointer to the original object.

Therefore, you need to use a property mappedBy

to communicate that the key to this relationship is on the other side.

In your case, you need to introduce annotation @OneToOne

on the target side:

@Entity
public class Product {

    @Id
    @Column(name = "ID")
    private String id;

    @OneToOne(mappedBy = "product")
    private ProductImage productImage;
}

@Entity
public class ProductImage {

    @Id
    @Column(name = "ID", unique = true)
    private String id;

    @OneToOne
    @JoinColumn(name = "product_ID")
    private Product product;

    @Column
    @Lob
    private Blob data;
}

      

0


source


JPA Objects, learn more about @PrimaryKeyJoinColumn

:

@Entity
public class Product {
    @Id
    private String id;

    @PrimaryKeyJoinColumn
    @OneToOne(orhanRemoval = true)
    private ProductImage image;
}

@Entity
public class ProductImage {
    @Id
    private String productId; // this will be foreign key as well as primary

   //other properties goes here
}

      

Database tables:

CREATE TABLE product (
    id VARCHAR PRIMARY KEY
);

CREATE TABLE product_image (
    product_id VARCHAR PRIMARY KEY REFERENCES product(id)
    -- other columns goes here
);

      

0


source







All Articles