JPA: one-to-one relationship with an entity of the exact type

Suppose you have the following database table:

CREATE TABLE IF NOT EXISTS USER (
    USER_NAME               VARCHAR(20) NOT NULL,
    FIRST_NAME              VARCHAR(50) NOT NULL,
    SECOND_NAME             VARCHAR(50) NOT NULL DEFAULT '',
    SURNAME                 VARCHAR(50) NOT NULL,
    BIRTH_DATE              DATE NOT NULL,
    BIRTH_GENDER            ENUM ('M', 'F') NOT NULL,
    CREATION_TIMESTAMP      TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    CREATED_BY              VARCHAR(20) NOT NULL,
    LAST_UPDATE_TIMESTAMP   TIMESTAMP NULL ON UPDATE CURRENT_TIMESTAMP,
    LAST_UPDATED_BY         VARCHAR(20),
    DELETION_TIMESTAMP      TIMESTAMP NULL,
    DELETED_BY              VARCHAR(20),

    PRIMARY KEY (USER_NAME),
    FOREIGN KEY (CREATED_BY) REFERENCES USER(USER_NAME),
    FOREIGN KEY (LAST_UPDATED_BY) REFERENCES USER(USER_NAME),
    FOREIGN KEY (DELETED_BY) REFERENCES USER(USER_NAME)
) CHARACTER SET utf8;

I have the following JPA object as follows:

/**
 * @author Buhake Sindi
 *
 */
@Entity
@Table(name="USER")
@Access(AccessType.FIELD)
public class User implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 1600376007707987934L;

    @Id
    @Column(name="USER_NAME", nullable=false)
    private String id;

    @Column(name="FIRST_NAME", nullable=false)
    private String firstName;

    @Column(name="SECOND_NAME", nullable=false)
    private String secondName;

    @Column(name="SURNAME", nullable=false)
    private String surname;

    @Temporal(TemporalType.DATE)
    @Column(name="BIRTH_DATE", nullable=false)
    private Date birthDate;

    @Column(name="BIRTH_GENDER", columnDefinition="ENUM('M', 'F')", nullable=false)
    @Enumerated(EnumType.STRING)
    private Gender birthGender;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name="CREATION_TIMESTAMP", insertable=false, updatable=false, nullable=false)
    private Date creationTimestamp;

    @OneToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="CREATED_BY", insertable=true, updatable=false, nullable=false)
    private User createdBy;

    /* (non-Javadoc)
     * @see za.co.sindi.entity.IDBasedEntity#getId()
     */
    public String getId() {
        // TODO Auto-generated method stub
        return id;
    }

    /* (non-Javadoc)
     * @see za.co.sindi.entity.IDBasedEntity#setId(java.io.Serializable)
     */
    public void setId(String id) {
        // TODO Auto-generated method stub
        this.id = id;
    }

    /**
     * @return the firstName
     */
    public String getFirstName() {
        return firstName;
    }

    /**
     * @param firstName the firstName to set
     */
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    /**
     * @return the secondName
     */
    public String getSecondName() {
        return secondName;
    }

    /**
     * @param secondName the secondName to set
     */
    public void setSecondName(String secondName) {
        this.secondName = secondName;
    }

    /**
     * @return the surname
     */
    public String getSurname() {
        return surname;
    }

    /**
     * @param surname the surname to set
     */
    public void setSurname(String surname) {
        this.surname = surname;
    }

    /**
     * @return the birthDate
     */
    public Date getBirthDate() {
        return birthDate;
    }

    /**
     * @param birthDate the birthDate to set
     */
    public void setBirthDate(Date birthDate) {
        this.birthDate = birthDate;
    }

    /**
     * @return the birthGender
     */
    public Gender getBirthGender() {
        return birthGender;
    }

    /**
     * @param birthGender the birthGender to set
     */
    public void setBirthGender(Gender birthGender) {
        this.birthGender = birthGender;
    }


    /* (non-Javadoc)
     * @see za.co.sindi.entity.AbstractIdentifiableAuditableEntity#getCreationTimestamp()
 */
    @Override
    public Date getCreationTimestamp() {
    // TODO Auto-generated method stub
    return creationTimestamp;
}

/* (non-Javadoc)
 * @see za.co.sindi.entity.AbstractIdentifiableAuditableEntity#setCreationTimestamp(java.util.Date)
 */
@Override
public void setCreationTimestamp(Date creationTimestamp) {
    // TODO Auto-generated method stub
    this.creationTimestamp = creationTimestamp;
}

/* (non-Javadoc)
 * @see za.co.sindi.entity.AbstractIdentifiableAuditableEntity#getCreatedBy()
 */
@Override
public User getCreatedBy() {
    // TODO Auto-generated method stub
    return createdBy;
}

/* (non-Javadoc)
 * @see za.co.sindi.entity.AbstractIdentifiableAuditableEntity#setCreatedBy(java.lang.Object)
 */
    @Override
    public void setCreatedBy(User createdBy) {
        // TODO Auto-generated method stub
        this.createdBy = createdBy;
    }
}

The problem is matching the attribute createdBywith CREATED_BY. When you deploy it to RedHat Wildfly 8.2.0 Final, it starts in an endless loop (StackOverflow error). How to properly display it so that the relationship can have one on one without a JPA that has gone crazy?


I don't know why this matters, but mine persistence.xmllooks like this:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1"
    xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
    <persistence-unit name="myapp-persistence-unit" transaction-type="JTA">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider><!-- used since Hibernate 4.3.x instead of org.hibernate.ejb.HibernatePersistence -->
        <jta-data-source>java:/jdbc/MyAppXADS</jta-data-source>
        <shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode><!-- This is the default anyway. -->
        <properties>
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>
            <property name="hibernate.hbm2ddl.auto" value="validate" /><!-- DBA are paid to create DB tables so never do update | create | create-drop. -->
            <property name="hibernate.cache.use_second_level_cache" value="true" />
            <property name="hibernate.show_sql" value="true" />
            <property name="hibernate.enable_lazy_load_no_trans" value="true"/>
        </properties>
    </persistence-unit> 
</persistence>
+4
source share
2 answers

, User @MappedSuperclass AbstractSoftDeleteAuditableEntity ( ). MappedSuperclass createdBy, lastUpdatedBy deletedBy User. Hibernate , User StackOverflowError. User , .

+1

, , , .

CREATED_BY NOT NULL; USER? - , .

( , , , , ), . , toString, equals hashCode ( USER, , , ).

, Hibernate , , , createdBy USER.

, , .

, TRACE org.hibernate, , .

+2

All Articles