Issue
I have three tables called user
, profile
, branch
and one more table to link these three, userprofilebranch
table.
My problem is
- Branch table is a master table from where I fetch some details and assign a branch to the user, where branch id is a PK.
- Same as branch I have a profile master table I do the same where profile id is PK.
- I have a user table while saving the user I want to persist the
branchid
,profileid
, anduserid
inuserprofilebranch
table.
User.java
public class User implements Serializable, UserDetails {
private static final long serialVersionUID = 1L;
@Id
@Column(name="USER_ID", nullable=false)
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long userId ;
@Column(name="USERNAME")
private String userName ;
@Column(name="FIRST_NAME")
private String firstName ;
@Column(name="LAST_NAME")
private String lastName ;
@OneToOne(optional=true, mappedBy="mappedUser")
private UserProfileBranch mappedUserProfileBranch;
public User() {
super();
}
public void setUserId( Long userId ) {
this.userId = userId ;
}
public Long getUserId() {
return this.userId;
}
public void setFirstName( String firstName ) {
this.firstName = firstName;
}
public String getFirstName() {
return this.firstName;
}
public void setLastName( String lastName ) {
this.lastName = lastName;
}
public String getLastName() {
return this.lastName;
}
}
UserProfileBranch.java
public class UserProfileBranch {
@EmbeddedId @AttributeOverrides({
@AttributeOverride(name="userId", column=@Column(name="USER_ID")),
@AttributeOverride(name="branchCode", column=@Column(name="BRANCH_CODE")),
@AttributeOverride(name="profileId", column=@Column(name="PROFILE_ID"))
})
private UserProfileBranchComposite userProfileBranchCompositeKey;
@OneToOne(optional=true,fetch= FetchType.LAZY) @PrimaryKeyJoinColumns({
@PrimaryKeyJoinColumn(name="USER_ID", referencedColumnName="USER_ID"),
@PrimaryKeyJoinColumn(name="BRANCH_CODE", referencedColumnName="BRANCH_CODE"),
@PrimaryKeyJoinColumn(name="PROFILE_ID", referencedColumnName="PROFILE_ID")
})
private User mappedUser;
public UserProfileBranchComposite getUserProfileBranchCompositeKey() {
return userProfileBranchCompositeKey;
}
public void setUserProfileBranchCompositeKey(
UserProfileBranchComposite userProfileBranchCompositeKey) {
this.userProfileBranchCompositeKey = userProfileBranchCompositeKey;
}
}
UserProfileBranchCompositeKey
@Embeddable
public class UserProfileBranchComposite implements Serializable{
private static final long serialVersionUID = 1L;
@Column(name="USER_ID",nullable= false)
private Long userId;
@Column(name="BRANCH_CODE",nullable= false)
private String branchCode;
@Column(name="PROFILE_ID")
private String profileId;
public UserProfileBranchComposite() {
}
public UserProfileBranchComposite(Long userId) {
this.userId = userId;
}
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public String getBranchCode() {
return branchCode;
}
public void setBranchCode(String branchCode) {
this.branchCode = branchCode;
}
public String getProfileId() {
return profileId;
}
public void setProfileId(String profileId) {
this.profileId = profileId;
}
}
when I execute the code I got this error
Caused by: org.hibernate.MappingException: broken column mapping for: mappedUser.id of: in.vit.leasing.security.domain.model.UserProfileBranch
at org.hibernate.persister.entity.AbstractPropertyMapping.initPropertyPaths(AbstractPropertyMapping.java:178)
at org.hibernate.persister.entity.AbstractPropertyMapping.initIdentifierPropertyPaths(AbstractPropertyMapping.java:242)
at org.hibernate.persister.entity.AbstractPropertyMapping.initPropertyPaths(AbstractPropertyMapping.java:222)
at org.hibernate.persister.entity.AbstractEntityPersister.initOrdinaryPropertyPaths(AbstractEntityPersister.java:2457)
at org.hibernate.persister.entity.AbstractEntityPersister.initPropertyPaths(AbstractEntityPersister.java:2494)
at org.hibernate.persister.entity.AbstractEntityPersister.postConstruct(AbstractEntityPersister.java:3949)
at org.hibernate.persister.entity.SingleTableEntityPersister.<init>(SingleTableEntityPersister.java:453)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
at org.hibernate.persister.internal.PersisterFactoryImpl.create(PersisterFactoryImpl.java:163)
at org.hibernate.persister.internal.PersisterFactoryImpl.createEntityPersister(PersisterFactoryImpl.java:135)
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:401)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1859)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:857)
I am not getting where I mapped wrong. can some one help me to fix this issue?
Solution
My advice from personal experience: don't use composite keys with Hibernate, use generated primary keys. Benefits:
- simpler mapping, less headaches
- less storage (one column for storing foreign keys, not three)
- better performance
If you want it the hard way: try to change the owner to User.java:
@OneToOne(optional=true)
@JoinColumns({
@JoinColumn(name="KEY_USER_ID", referencedColumnName="USER_ID", updateable=false, insertable=false),
@JoinColumn(name="KEY_BRANCH_CODE", referencedColumnName="BRANCH_CODE", updateable=false, insertable=false),
@JoinColumn(name="KEY_PROFILE_ID", referencedColumnName="PROFILE_ID", updateable=false, insertable=false)
})
private UserProfileBranch mappedUserProfileBranch;
Answered By - Journeycorner