简体   繁体   中英

JPA annotate composite primary key that is also a one to many foreign key

Been working on this for a couple of days and haven't yet seen an example that matches what I'm trying to do or I'm missing it as I'm a bit new to Hibernate and JPA. I'm attempting to convert some hibernate code over to JPA and can't seem to get a particular join correct.

Here is my table structure:

Table AppUser

  • id (PK)

Table SecurityQuestion

  • id (PK)

Table AppUserSecurityQuestion

  • AppUserId (PK, FK to AppUser.id)

  • SecurityQuestionId (PK, FK to SecurityQuestion.id)

And here is what I've tried to far with my domains (just relevant property declarations):

BaseEntity.java

@MappedSuperclass
public abstract class BaseEntity implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="id", updatable=false, nullable=false)
    private Integer id;
    ...
}

AppUser.java

@Entity
@Table(name="AppUser")
public class AppUser extends BaseEntity {
    @OneToMany(fetch=FetchType.EAGER)
    @MapKeyJoinColumn(name="AppUserId")
    private Set<AppUserSecurityQuestion> securityAnswers;
    ...
}

AppUserSecurityQuestion.java

@Entity
@Table(name="AppUserSecurityQuestion")
public class AppUserSecurityQuestion implements java.io.Serializable {
    @EmbeddedId
    private AppUserSecurityQuestionId id;
    ...
}

AppUserSecurityQuestionId.java

@Embeddable
public class AppUserSecurityQuestionId implements java.io.Serializable {
    private AppUser appUser;
    private SecurityQuestion securityQuestion;
    ...
}

This was working with hibernate configuration but again I'm attempting to convert it over to JPA. Here are the relevant pieces of the hbm files:

AppUser.hbm.xml

<hibernate-mapping default-access="field">
    <class catalog="WEBR" name="testapp.domain.AppUser" schema="dbo" table="AppUser">
        <id name="appUserId" type="java.lang.Integer">
            <column name="AppUserId" />
            <generator class="org.hibernate.id.enhanced.SequenceStyleGenerator">
                <param name="sequence_name">AppUserSeq</param>
            </generator>
        </id>
        ...
        <set name="securityAnswers" table="AppUserSecurityQuestion" inverse="true" lazy="false">
            <key column="AppUserId" not-null="true" />
            <one-to-many class="testapp.domain.AppUserSecurityQuestion" />
        </set>


    </class>
</hibernate-mapping>

AppUserSecurityQuestion.hbm.xml

<hibernate-mapping>
    <class name="testapp.domain.AppUserSecurityQuestion" table="AppUserSecurityQuestion" schema="dbo" catalog="TEST">
        <composite-id name="id" class="testapp.domain.AppUserSecurityQuestionId">
            <key-many-to-one name="appUser" class="testapp.domain.AppUser">
                <column name="id"/>
            </key-many-to-one>
            <key-many-to-one name="securityQuestion" class="testapp.domain.SecurityQuestion">
                <column name="SecurityQuestionId" />
            </key-many-to-one>
        </composite-id>
        <property name="answer" type="java.lang.String">
            <column name="Answer" not-null="true" />
        </property>
    </class>
</hibernate-mapping>

I'm basically just trying to look at the hbm's and convert each piece over to JPA but I'm apparently missing something as I get this exception when I try to access data through the application:

org.hibernate.exception.SQLGrammarException: could not extract ResultSet ... Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: Invalid object name 'AppUser_AppUserSecurityQuestion'

Here is the HQL as well:

select securityan0_.AppUser_id as AppUser_1_0_0_, securityan0_.securityAnswers_appUser as security2_3_0_, securityan0_.securityAnswers_securityQuestion as security3_3_0_, appusersec1_.appUser as appUser1_2_1_, appusersec1_.securityQuestion as security2_2_1_, appusersec1_.Answer as Answer3_2_1_ from AppUser_AppUserSecurityQuestion securityan0_ inner join AppUserSecurityQuestion appusersec1_ on securityan0_.securityAnswers_appUser=appusersec1_.appUser and securityan0_.securityAnswers_securityQuestion=appusersec1_.securityQuestion where securityan0_.AppUser_id=?

I've obviously got my joins declared incorrectly but I'm not sure what else to try at this point. Anybody see what I'm doing wrong?

Figured it out...At least it appears to be working the way I need it to. Here are the changes I needed to make:

AppUser.java

@Entity
@Table(name="AppUser")
public class AppUser extends BaseEntity {
    @OneToMany(mappedBy="id.appUser", fetch=FetchType.EAGER)
    @MapKeyJoinColumn(name="id")
    private Set<AppUserSecurityQuestion> securityAnswers;
    ...
}

AppUserSecurityQuestionId.java

@Embeddable
public class AppUserSecurityQuestionId implements java.io.Serializable {
    @ManyToOne
    @JoinColumn(name="AppUserId")
    private AppUser appUser;
    @ManyToOne
    @JoinColumn(name="SecurityQuestionId")
    private SecurityQuestion securityQuestion;
    ...
}

Everything else remained as is.

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