I am having an issue saving a one to many relationship. It seems that it is saving the elements of the list on the table, but it does not save the foreign key in the proper table.
@Entity
@Table(name = "tbl_applications")
public class ApplicationEntity
{
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "intAPI", referencedColumnName = "intCode")
private ApiResourceEntity objApi;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "strApplication")
List<ApplicationRoleEntity> colApplicationRoles = new ArrayList<ApplicationRoleEntity>();
@OneToMany(cascade = CascadeType.ALL, mappedBy = "strApplication")
List<URLEntity> colUrls = new ArrayList<URLEntity>();
@OneToMany(cascade = CascadeType.ALL, mappedBy = "strApplication")
List<KeyCredentialEntity> colKeyCredentials = new ArrayList<KeyCredentialEntity>();
@OneToMany(cascade = CascadeType.ALL, mappedBy = "strApplication")
List<PasswordCredentialEntity> colPasswordCredentials = new ArrayList<PasswordCredentialEntity>();
@OneToMany(cascade = CascadeType.ALL, mappedBy = "strApplication")
List<RequiredResourceAccessEntity> colRequiredResourceAccess = new ArrayList<RequiredResourceAccessEntity>();
}
@Entity
@Table(name = "tbl_apiresources")
public class ApiResourceEntity
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "intCode")
private Integer intCode;
private Integer intRequestedAccessTokenVersion;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "intCode")
private List<PermissionScopeEntity> colOauth2PermissionsScope = new ArrayList<PermissionScopeEntity>();
}
@Entity
@Table(name = "tbl_permissionsscope")
public class PermissionScopeEntity
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "intCode")
private Integer intCode;
private String strAdminConsentDescription;
private String strAdminConsentDisplayName;
private String strID;
private Boolean bolIsEnabled;
private String strOrigin;
private String strType;
private String strUserConsentDescription;
private String strUserConsentDisplayName;
private String strValue;
}
an example of what it saved on the database:
tbl_applications
intAPI = 1
tbl_apiresources
intCode = 1
intRequestAccessTokenVersion = 2
intOauth2PermissionScopes = NULL
tbl_permissionsscope
intCode = 1
strAdminConsentDescription = xxxxxx
strAdminConsentDisplayName = xxxxxx
strID = xxxxxx
bolIsEnabled = xxxxxx
strOrigin = xxxxxx
strType = xxxxxx
strUserConsentDescription = xxxxxx
strUserConsentDisplayName = xxxxxx
strValue = xxxxxx
it saves the elements of the list (Permissions Scope), however the foreign key is not save on the table tbl_apiresources. Maybe because the identifier is an Identity Field (Self Generated)
All the @OneToMany relationships of the ApplicationEntity Object are saved properly. @OneToMany can not point to @ManyToOne as I get a circular reference exception
When you specify only a @OneToMany
relationship, ie, unidirectional from Parent to Child, hibernate will implement the mapping with a join table. When you save a parent/child relation the keys are inserted into the join table:
@Entity
public class Parent {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
@OneToMany
Set<Child> children;
}
@Entity
public class Child {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
}
Results in the join table parent_child
Hibernate: create sequence hibernate_sequence start with 1 increment by 1
Hibernate: create table child (id bigint not null, primary key (id))
Hibernate: create table parent (id bigint not null, primary key (id))
Hibernate: create table parent_children (parent_id bigint not null, children_id bigint not null, primary key (parent_id, children_id))
Hibernate: alter table parent_children add constraint UK_fh9rqlaf2416b31ec7n92nrfh unique (children_id)
Hibernate: alter table parent_children add constraint FK2li53iimvay1c1bjvc1hed3gl foreign key (children_id) references child
Hibernate: alter table parent_children add constraint FKdnxvj4hlnv40nix37bpjsvecn foreign key (parent_id) references parent
Hibernate: call next value for hibernate_sequence
Hibernate: insert into child (id) values (?)
Hibernate: call next value for hibernate_sequence
Hibernate: insert into parent (id) values (?)
Hibernate: insert into parent_children (parent_id, children_id) values (?, ?)
If you want the FK to be in the child table, and you do, then define a unidirectional mapping from the child to the parent.
@Entity
public class Parent {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
}
@Entity
public class Child {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
@ManyToOne
Parent parent;
}
Which does not create a join table
Hibernate: create sequence hibernate_sequence start with 1 increment by 1
Hibernate: create table child (id bigint not null, parent_id bigint, primary key (id))
Hibernate: create table parent (id bigint not null, primary key (id))
Hibernate: alter table child add constraint FK7dag1cncltpyhoc2mbwka356h foreign key (parent_id) references parent
Hibernate: call next value for hibernate_sequence
Hibernate: insert into parent (id) values (?)
Hibernate: call next value for hibernate_sequence
Hibernate: insert into child (parent_id, id) values (?, ?)
If you want a bidirectional mapping than add both but understand that you should do persistence like the second example and use the parent Set<Child> children
for queries only for performance reasons.
@Entity
public class Parent {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
@OneToMany
Set<Child> children;
}
@Entity
public class Child {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
@ManyToOne
Parent parent;
}
After inserting, then query with left outer join fetch
or better by using an EntityGraph
.
"from Parent p left outer join fetch p.children where p.id = :id"
Kindly find below the modifications that I made to the code
@Entity
@Table(name = "tbl_applications")
public class ApplicationEntity
{
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "intAPI", referencedColumnName = "intCode")
private ApiResourceEntity objApi;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "strApplication")
List<ApplicationRoleEntity> colApplicationRoles = new ArrayList<ApplicationRoleEntity>();
@OneToMany(cascade = CascadeType.ALL, mappedBy = "strApplication")
List<URLEntity> colUrls = new ArrayList<URLEntity>();
@OneToMany(cascade = CascadeType.ALL, mappedBy = "strApplication")
List<KeyCredentialEntity> colKeyCredentials = new ArrayList<KeyCredentialEntity>();
@OneToMany(cascade = CascadeType.ALL, mappedBy = "strApplication")
List<PasswordCredentialEntity> colPasswordCredentials = new ArrayList<PasswordCredentialEntity>();
@OneToMany(cascade = CascadeType.ALL, mappedBy = "strApplication")
List<RequiredResourceAccessEntity> colRequiredResourceAccess = new ArrayList<RequiredResourceAccessEntity>();
}
@Entity
@Table(name = "tbl_apiresources")
public class ApiResourceEntity
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "intCode")
private Integer intCode;
private Integer intRequestedAccessTokenVersion;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "intCode")
private List<PermissionScopeEntity> colOauth2PermissionsScope = new ArrayList<PermissionScopeEntity>();
}
@Entity
@Table(name = "tbl_permissionsscope")
public class PermissionScopeEntity
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "intCode")
private Integer intCode;
private String strAdminConsentDescription;
private String strAdminConsentDisplayName;
private String strID;
private Boolean bolIsEnabled;
private String strOrigin;
private String strType;
private String strUserConsentDescription;
private String strUserConsentDisplayName;
private String strValue;
@ManyToOne
private ApiResourceEntity objApi;
}
If I only let the annotation @OneToMany on the ApiResourceEntity I got the exception mentioned above
java.lang.IllegalStateException: org.hibernate.TransientObjectException: object circular reference on transient instance - circular reference on transient instance: azure.entities.PermissionScopeEntity
When I add the cascade = CascadeType.ALL I got the following error:
org.hibernate.engine.jdbc.spi.SqlExceptionHelper - Invalid column name 'objApi_intCode'.
with and without the mappedBy = "intCode"
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.