简体   繁体   中英

How can a UUID be shared as a primary key in two tables using Hibernate?

I am using MySql as the database and aim to store the generated UUID in Binary(16) format. In the DB I have two tables:

  1. To store the details of the user.
  2. To store the password of the user.

I have two entities UserDetails and UserLogin to represent these tables, respectively. They are as follows:

UserDetails class:

package Entities

import org.hibernate.annotations.GenericGenerator
import org.hibernate.annotations.Type
import java.io.Serializable
import java.util.*
import javax.persistence.*

/**
 * class UserDetails
 */
@Entity
@Table(name = "user_details")
data class UserDetails(
        /**
         * The first name field for the user details table.
         */
        @Column(name = "first_name") var firstName: String,
        /**
         * The last name field for the user details table.
         */
        @Column(name = "last_name") var lastName: String,
        /**
         * The phone number field for the user details table.
         */
        @Column(name = "phone_number") var phoneNumber: String,
        /**
         * The area code field for the user details table.
         */
        @Column(name = "area_code") var areaCode: String,
        /**
         * The rating field for the user details table.
         */
        @Column(name = "rating") var rating: Double,
        /**
         * The user login information containing the password for the user.
         */
        @OneToOne(cascade = arrayOf(CascadeType.ALL), mappedBy = "user_id") @PrimaryKeyJoinColumn
        var userLogin: UserLogin
): Serializable {

    /**
     * The UserId field for the user details table.
     */
    @Id @Type(type = "uuid-binary")
    @GeneratedValue(generator = "uuid2") @GenericGenerator(name = "uuid2", strategy = "uuid2")
    @Column(name = "user_id") lateinit var userId: UUID

    @Suppress("unused")
    constructor() : this("", "", "", "", 0.0, UserLogin())

    companion object {
        @JvmStatic val serialVersionUID: Long = 1L
    }
}

UserLogin Class:

package Entities

import java.io.Serializable
import java.util.*
import javax.persistence.*

/**
 * class UserLogin
 *
 * This table is supposed to be temporary. The frontend has to run on mobile devices which will be using the OTP through
 * SMS to login to the app. Once that is done there is no need for this table and can be safely deleted w/o having to
 * modify a huge user_details table.
 *
 * @author niksinghal
 */
@Entity
@Table(name = "user_login_details")
data class UserLogin(
        /**
         * The password field for the login table.
         * It has to store the encrypted password.
         */
        @Column(name = "password", nullable = false) var password: String
): Serializable {

    /**
     * The user ID field for the login table.
     * This value is a shared primary key and it is populated by the UserDetails.userId field
     */
    @Id @OneToOne lateinit var userId: UUID

    @Suppress("unused")
    constructor() : this("")

    companion object {
        @JvmStatic val serialVersionUID: Long = 1L
    }
}

The aim is to have one password for every user detail row (OneToOne Mapping) and have the same value for the primary keys userId.

I am compiling this and getting - Invocation of init method failed; nested exception is org.hibernate.AnnotationException: @OneToOne or @ManyToOne on Entities.UserLogin.userId references an unknown entity: java.util.UUID

I am very new to this and doing all of this strictly to learn Hibernate concepts. That being said, my understanding is that the UserDetails class' userId will be generated by the generator. The @OneToOne & @PrimaryKeyJoinColumn annotations above the UserDetails' UserLogin should push the generated UUID to the UserLogin's userId which is again marked by @OneToOne.

Kindly let me know why I am getting the error? And if I will be able to store the UUID in binary(16) in the DB?

The OneToOne annotation is used to associate whole Entities, not single values. You need to tell Hibernate how it should generate your key.

And there are existing SOF-Threads that answered your question. For example this Thread

I was doing many things wrong here:

  • Firstly, I was using the mappedBy wrong. The value of mappedBy has to be a field in the class or the name of the class with the name starting in lower case. I was using the name of the column in the actual table.

  • Secondly, I was trying to implement the unidirectional 1-1 relationship (I learned this later) between the two tables. The aim was to share the primary key. That has to be done using the @OneToOne and @PrimaryKeyJoinColumn annotations on the userLogin in UserDetails class.

  • Thirdly, Dexter is right. @OneToOne can be used only on Entities.

  • Fourthly, I hadn't placed a constraint in the table in DB.

    Good news is that the UUID to binary works! Yay!!

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