简体   繁体   中英

Unidirectional @OneToOne using IDs

I want to create a @OneToOne unidirectional relationship using ID's. Let's consider following example:

@Table(name = "user")
@Entity
class User (

    @Id
    @GeneratedValue(...)
    var id: Long? = null,

    @OneToOne
    var address: UserAddress? = null
)

@Table(name = "user_address")
@Entity
class UserAddress(
    @Id
    var id: Long? = null,

    (...)
)

On database there is a foreign key constraint on user_address.id referencing user.id . I tried using many different annotation combinations, but I still had a problem with deletion. I am using JpaRepository of User and when userRepository.deleteById(id) is called, only child ( address ) is deleted, but not a parent ( user ). I would realy like to keep @Id columns with name "id". Is it even possible?

EDIT

When I use following code:

@Table(name = "user")
@Entity
class User (

    @Id
    @GeneratedValue(...)
    var id: Long? = null,

    @OneToOne(cascade = [CascadeType.All])
    @JoinColumn(name = "id", referencedColumnName = "id")
    var address: UserAddress? = null
)

@Table(name = "user_address")
@Entity
class UserAddress(
    @Id
    var id: Long? = null,


    @OneToOne(mappedBy = "address")
    var user: User? = null
    (...)
)

When userRepository.deleteById(id) is called, only child is deleted. I have no idea why... In addition I would like to keep this relation unidirectional.

EDIT User repository

@Repository
interface UserRepository : JpaRepository<User, Long> {
}

EDIT - SOLVED Ok. I have another entity (let's call it Company) which has Set<User> . It turns out that having it Fetch. EAGER prevents the user from being deleted... Thank everyone for your time. I had no idea that it might be a problem thus I haven't mentioned it...

What you need is a cascading delete, which you can achieve by passing orphanRemoval=true to your @OneToOne annotation.

Example:

    @OneToOne(orphanRemoval=true)
    var address: UserAddress? = null

Alternatively, you could also use cascade=CascadeType.REMOVE instead of orphanremoval=true .

Borrowed from ObjectDB :

If orphanRemoval=true is specified the disconnected Address instance is automatically removed. This is useful for cleaning up dependent objects (eg Address) that should not exist without a reference from an owner object (eg Employee). If only cascade=CascadeType.REMOVE is specified no automatic action is taken since disconnecting a relationship is not a remove operation.

Hope this helps!

Various issues.

  • The mappings are the wrong way round. @JoinColumn needs to be on other side ie that with the FK. The way you have defined it at the moment you are effectively saying that Address is dependent on (has a FK to) Address.

  • You have redefined the @Id field on the dependent entity even though it derives its ID from the User entity. You need to remove that and indicate that it is a shared Primary Key relationship here by annotating the relationship with @Id .

Given this you will need to make this a bidirectional relationship :

User:

@Table(name = "user")
@Entity
class User (

    @Id
    @GeneratedValue(...)
    var id: Long? = null,

    @OneToOne(cascade = [CascadeType.All], mappedBy="user")
    var address: UserAddress? = null
)

Address:

@Table(name = "user_address")
@Entity
class UserAddress(
    @Id
    @OneToOne
    @JoinColumn(name = "id", referencedColumnName = "id")
    var user: User? = null
    (...)
) 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM