Does Hibernate support individual associations like pkeys?

Can someone tell me if Hibernate supports associations as a pkey object? I thought this would be supported, but I have a lot of problems getting any kind of mapping that represents this for work. In particular, with direct mapping below:

@Entity public class EntityBar { @Id @OneToOne(optional = false, mappedBy = "bar") EntityFoo foo // other stuff } 

I get org.hibernate.MappingException: "Could not determine type for: EntityFoo, in table: ENTITY_BAR, for columns: [org.hibernate.mapping.Column (foo)]"

Diving into the code, it seems that the identifier is always considered a type of Value; that is, "everything that is stored by value, not by reference." This is essentially a Hibernate type, as well as zero or more columns. "I could make my EntityFoo value type by declaring it serializable, but I would not expect this to produce the correct result either.

I would have thought that Hibernate would consider the column type as an integer (or regardless of the actual type of the parent identifier), as it would with a regular one-to-one link, but that does not mean t appears when I also declare it an identifier . Am I going beyond what is possible by trying to combine @OneToOne with @Id? And if so, how can one reasonably model these relationships?

+4
source share
4 answers

If the goal is to have a shared primary key , what about it (inspired by the Java Persistence With Hibernate sample and tested in a pet database):

 @Entity public class User { @Id @GeneratedValue private Long id; @OneToOne(cascade = CascadeType.ALL) @PrimaryKeyJoinColumn private Address shippingAddress; //... } 

This is the "parent" class, which is first inserted and receives the generated identifier. Address as follows:

 @Entity public class Address implements Serializable { @Id @GeneratedValue(generator = "myForeignGenerator") @org.hibernate.annotations.GenericGenerator( name = "myForeignGenerator", strategy = "foreign", parameters = @Parameter(name = "property", value = "user") ) @Column(name = "ADDRESS_ID") private Long id; @OneToOne(mappedBy="shippingAddress") @PrimaryKeyJoinColumn User user; //... } 

With the above objects, it seems to look as expected:

 User newUser = new User(); Address shippingAddress = new Address(); newUser.setShippingAddress(shippingAddress); shippingAddress.setUser(newUser); // Bidirectional session.save(newUser); 

When saving Address value of the primary key that is inserted matches the primary key value of the User instance referenced by the User property.

Downloading only User or Address also works.

Let me know if I missed something.


PS: Strictly answer the question, according to Primary keys through OneToOne relationships :

JPA 1.0 does not allow @Id on OneToOne or ManyToOne, but JPA 2.0 does.

But , a version of Hibernate compatible with JPA 1.0

allows you to use the @Id annotation to display OneToOne or ManyToOne *.

I could not get this to work with Hibernate EM 3.4, though (it worked with Hibernate EM 3.5.1, i.e. with the implementation of JPA 2.0). Maybe I did something wrong.

In any case, using a shared primary key seems to provide the right solution.

+2
source

Yes it is possible.

See the following example using the Driver class and DriverId as the identifier for the driver.

 @Entity public class Drivers { private DriversId id; //The ID which is located in another class public Drivers() { } @EmbeddedId @AttributeOverrides({ @AttributeOverride(name = "personId", column = @Column(name = "person_id", nullable = false))}) @NotNull public DriversId getId() { return this.id; } //rest of class } 

Here we use personId as an identifier for the driver

And the DriversId class:

 //composite-id class must implement Serializable @Embeddable public class DriversId implements java.io.Serializable { private static final long serialVersionUID = 462977040679573718L; private int personId; public DriversId() { } public DriversId(int personId) { this.personId = personId; } @Column(name = "person_id", nullable = false) public int getPersonId() { return this.personId; } public void setPersonId(int personId) { this.personId = personId; } public boolean equals(Object other) { if ((this == other)) return true; if ((other == null)) return false; if (!(other instanceof DriversId)) return false; DriversId castOther = (DriversId) other; return (this.getPersonId() == castOther.getPersonId()); } public int hashCode() { int result = 17; result = 37 * result + this.getPersonId(); return result; } } 
+1
source

You can do this by splitting the primary key between EntityFoo and EntityBar:

 @Entity public class EntityBar { @Id @OneToOne @JoinColumn(name = "foo_id") EntityFoo foo; // other stuff } @Entity public class EntityFoo { @Id @GeneratedValue Integer id; // other stuff } 
0
source

Here you should use @EmbeddedId instead of @Id . And EntityFoo should be Embeddable .

Another way is to put an integer, and OneToOne with updateble and instertable is false.

0
source

Source: https://habr.com/ru/post/1306931/


All Articles