java - JPA Foreign Key constraint violation cannot insert Null -
i have simple user , roles entities 1 many mapping. 1 user many roles. getting error when try save user entity. setting role object user before calling persist.
below snap shot of entities.
user:
package com.petpe.ejbadmin.entity; import java.io.serializable; import java.util.date; import java.util.set; import javax.annotation.generated; import javax.persistence.basic; import javax.persistence.cascadetype; import javax.persistence.column; import javax.persistence.entity; import javax.persistence.fetchtype; import javax.persistence.generatedvalue; import javax.persistence.generationtype; import javax.persistence.id; import javax.persistence.namedqueries; import javax.persistence.namedquery; import javax.persistence.onetomany; import javax.persistence.table; import javax.persistence.temporal; import javax.persistence.temporaltype; import javax.validation.constraints.notnull; import javax.validation.constraints.size; import javax.xml.bind.annotation.xmlrootelement; import javax.xml.bind.annotation.xmltransient; @entity @table(name = "users") @xmlrootelement @namedqueries({ @namedquery(name = "user.findall", query = "select u user u"), @namedquery(name = "user.findbyusernameandpassword", query = "select u user u u.username = :username , u.password = :password"), @namedquery(name = "user.findbyuserfirstname", query = "select u user u u.userfirstname = :userfirstname"), @namedquery(name = "user.findbyuserlastname", query = "select u user u u.userlastname = :userlastname"), @namedquery(name = "user.findbyphonenumber", query = "select u user u u.phonenumber = :phonenumber"), @namedquery(name = "user.findbyemail", query = "select u user u u.email = :email"), @namedquery(name = "user.findbyerpid", query = "select u user u u.erpid = :erpid"), @namedquery(name = "user.findbybuyerid", query = "select u user u u.buyerid = :buyerid"), @namedquery(name = "user.findbycreateddate", query = "select u user u u.createddate = :createddate"), @namedquery(name= "user.findbyfirstletter",query="select u user u join fetch u.roleset ur lower(u.userfirstname) :firstname"), @namedquery(name= "user.findallusers",query="from user u join fetch u.roleset ur")}) public class user implements serializable { private static final long serialversionuid = 1l; @id @generatedvalue(strategy=generationtype.identity) @basic(optional = true) @column(name = "user_id") private integer userid; @size(max = 120) @column(name = "username") private string username; @size(max = 60) @column(name = "userfirstname") private string userfirstname; @size(max = 60) @column(name = "userlastname") private string userlastname; @size(max = 50) @column(name = "password") private string password; @size(max = 20) @column(name = "phonenumber") private string phonenumber; // @pattern(regexp="[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?", message="invalid email")//if field contains email address consider using annotation enforce field validation @size(max = 50) @column(name = "email") private string email; @size(max = 250) @column(name = "erpid") private string erpid; @size(max = 250) @column(name = "buyerid") private string buyerid; @basic(optional = false) @notnull @column(name = "created_date") @temporal(temporaltype.date) private date createddate; @onetomany(cascade = cascadetype.all, mappedby = "user", fetch = fetchtype.lazy) private set<role> roleset; public user() { } public user(integer userid) { this.userid = userid; } public user(integer userid, date createddate) { this.userid = userid; this.createddate = createddate; } public integer getuserid() { return userid; } public void setuserid(integer userid) { this.userid = userid; } public string getusername() { return username; } public void setusername(string username) { this.username = username; } public string getuserfirstname() { return userfirstname; } public void setuserfirstname(string userfirstname) { this.userfirstname = userfirstname; } public string getuserlastname() { return userlastname; } public void setuserlastname(string userlastname) { this.userlastname = userlastname; } public string getpassword() { return password; } public void setpassword(string password) { this.password = password; } public string getphonenumber() { return phonenumber; } public void setphonenumber(string phonenumber) { this.phonenumber = phonenumber; } public string getemail() { return email; } public void setemail(string email) { this.email = email; } public string geterpid() { return erpid; } public void seterpid(string erpid) { this.erpid = erpid; } public string getbuyerid() { return buyerid; } public void setbuyerid(string buyerid) { this.buyerid = buyerid; } public date getcreateddate() { return createddate; } public void setcreateddate(date createddate) { this.createddate = createddate; } @xmltransient public set<role> getroleset() { return roleset; } public void setroleset(set<role> roleset) { this.roleset = roleset; } @override public int hashcode() { int hash = 0; hash += (userid != null ? userid.hashcode() : 0); return hash; } @override public boolean equals(object object) { // todo: warning - method won't work in case id fields not set if (!(object instanceof user)) { return false; } user other = (user) object; if ((this.userid == null && other.userid != null) || (this.userid != null && !this.userid.equals(other.userid))) { return false; } return true; } @override public string tostring() { return "[ userid=" + userid + " ]"; } }
role:
/* * change license header, choose license headers in project properties. * change template file, choose tools | templates * , open template in editor. */
package com.petpe.ejbadmin.entity; import java.io.serializable; import javax.persistence.basic; import javax.persistence.column; import javax.persistence.entity; import javax.persistence.fetchtype; import javax.persistence.generatedvalue; import javax.persistence.generationtype; import javax.persistence.id; import javax.persistence.joincolumn; import javax.persistence.manytoone; import javax.persistence.namedqueries; import javax.persistence.namedquery; import javax.persistence.table; import javax.validation.constraints.notnull; import javax.validation.constraints.size; import javax.xml.bind.annotation.xmlrootelement; @entity @table(name = "user_roles") @xmlrootelement public class role implements serializable { private static final long serialversionuid = 1l; @id @generatedvalue(strategy=generationtype.identity) @basic(optional = false) @column(name = "roleid") private integer roleid; @basic(optional = false) @notnull @size(min = 1, max = 30) @column(name = "rolename") private string rolename; @joincolumn(name = "user_id", referencedcolumnname = "user_id") @manytoone( fetch = fetchtype.lazy) private user user; public role() { } public role(string rolename) { this.rolename = rolename; } public role(integer roleid, string rolename) { this.roleid = roleid; this.rolename = rolename; } public user getuser() { return user; } public void setuser(user user) { this.user = user; } public integer getroleid() { return roleid; } public void setroleid(integer roleid) { this.roleid = roleid; } public string getrolename() { return rolename; } public void setrolename(string rolename) { this.rolename = rolename; } @override public int hashcode() { int hash = 0; hash += (roleid != null ? roleid.hashcode() : 0); return hash; } @override public boolean equals(object object) { // todo: warning - method won't work in case id fields not set if (!(object instanceof role)) { return false; } role other = (role) object; if ((this.roleid == null && other.roleid != null) || (this.roleid != null && !this.roleid.equals(other.roleid))) { return false; } return true; } @override public string tostring() { return "[ roleid=" + roleid + " ]"; } }
error:
1.cannot insert value null column 'user_id', table 'pedb.pedb.user_roles'; column not allow nulls. insert fails. 2.could not insert: [com.petpe.ejbadmin.entity.role] 3.org.hibernate.exception.constraintviolationexception: not insert: [com.petpe.ejbadmin.entity.role] 4.javax.persistence.persistenceexception: org.hibernate.exception.constraintviolationexception: not insert: [com.petpe.ejbadmin.entity.role]
setting , persisting code:
public boolean addormodifyuser(useradmindto udato) { user usr=this.populateuserobj(udato); pet_em.persist(usr); return true; } public user populateuserobj(useradmindto udto) { user usr=new user(); usr.setbuyerid(udto.getbuyerid()); usr.setcreateddate(new date()); usr.setemail(udto.getemail()); usr.seterpid(udto.geterpid()); usr.setpassword(udto.getpassword()); usr.setphonenumber(udto.getphonenumber()); usr.setuserfirstname(udto.getfirstname()); usr.setuserlastname(udto.getlastname()); usr.setusername(udto.getusername()); for(role r: udto.getrole()) { set<role> roleset=new hashset<>(); roleset.add(r); usr.setroleset(roleset); } return usr; }
layout of table:
so have not null
constraint on user_id
inside roles tables. when persisting (even cascading relationships), foreign key (or entity relationship) not automagically set itself.
most when creating role
, did not set user
, when persisting, provider has no idea user_id
is, tries set null in db, violation of db schema.
all need set user
each role
set<role> roleset=new hashset<>(); for(role r: udto.getrole()) { r.setuser(usr); // <------ roleset.add(r); } usr.setroleset(roleset);
also notice set
created outside loop
and...but...wait...
you're not out woods yet. above solve error, still have problem. it's subtle , lead hard find bugs.
you have role
id being generated.
@id @generatedvalue(strategy=generationtype.identity) private integer roleid;
so don't set when creating role
set<role> roles = new hashset<>(); role userrole = new role("user"); userrole.setuser(user); roles.add(userrole); role coolrole = new role("cool_guy"); coolrole.setuser(user); roles.add(coolrole); user.setroleset(roles);
doesn't problem, bug in hashcode
@override public int hashcode() { int hash = 0; hash += (roleid != null ? roleid.hashcode() : 0); return hash; }
the hashcode
consists of roleid
. don't set roleid
because supposed generated. when add roles set
, have same hashcode
, add 1 role
set
, objects in set
cannot have same hashcode
.
to fix this, can change hashcode
include rolename
.
while testing, had netbeans generate hashcode
, equals
. here's result.
@override public int hashcode() { int hash = 7; hash = 31 * hash + objects.hashcode(this.roleid); hash = 31 * hash + objects.hashcode(this.rolename); return hash; } @override public boolean equals(object obj) { if (obj == null) { return false; } if (getclass() != obj.getclass()) { return false; } final role other = (role) obj; if (!objects.equals(this.roleid, other.roleid)) { return false; } if (!objects.equals(this.rolename, other.rolename)) { return false; } return true; }
that should fix bug.
Comments
Post a Comment