JPA find() does not load Entity #Id - java

I'm starting to use JPA with the OpenJPA API, and i'm having a problem with the find().
Here are the tables:
CREATE TABLE compania (
ID int(11) NOT NULL,
NOMBRE varchar(45) DEFAULT NULL,
PRIMARY KEY (ID)
)
CREATE TABLE modelo (
ID int(11) NOT NULL,
ID_COMPANIA int(11) DEFAULT NULL,
NOMBRE_MODELO varchar(45) DEFAULT NULL,
PRIMARY KEY (ID),
KEY MODELO_COMPANIA_FK_idx (ID_COMPANIA),
CONSTRAINT MODELO_COMPANIA_FK FOREIGN KEY (ID_COMPANIA) REFERENCES compania (ID)
)
and here are my Entities:
#Entity
public class Compania extends EntityJPA{
private static final long serialVersionUID = 1L;
#Id
private int id;
#Column
private String nombre;
#OneToMany(mappedBy="compania",cascade={CascadeType.ALL})
#JoinColumn(name="ID_COMPANIA", nullable=false)
private List<Modelo> listaModelos;
public Compania() {
}
public int getId() {
return id;
}
public void setId(int idCompania) {
this.id = idCompania;
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombreCompania) {
this.nombre = nombreCompania;
}
public List<Modelo> getListaModelos() {
return listaModelos;
}
public void setListaModelos(List<Modelo> listaModelos) {
this.listaModelos = listaModelos;
}
}
#Entity
public class Modelo extends EntityJPA{
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
#Column(name="NOMBRE_MODELO")
private String nombreModelo;
#ManyToOne
#JoinColumn(name="ID_COMPANIA", referencedColumnName="ID")
private Compania compania;
public Modelo() {
}
public Compania getCompania() {
return compania;
}
public void setCompania(Compania compania) {
this.compania = compania;
}
public int getId() {
return id;
}
public void setId(int idModelo) {
this.id = idModelo;
}
public String getNombre() {
return nombreModelo;
}
public void setNombre(String nombreModelo) {
this.nombreModelo = nombreModelo;
}
}
At the moment I make the
Compania cia = getEntityManager().find(Compania.class, idCompania);
the cia object does not have the value of the #Id attribute, it has the value of nombre but not of id. I mean:
cia.getId() = 0
and it must be 1 or 2 , etc. Not 0.
Thank you very much for your help.
I do not have the code to persist because It was already persisted.
the code for the find is
public static Compania findCompania(int idCompania){
try {
Compania cia = getEntityManager().find(Compania.class, idCompania);
return cia;
} finally {
closeEntityManager();
}
}
And if I activate the log, this is the select it shows:
482 testMySql TRACE [http-bio-8080-exec-5] openjpa.jdbc.SQL - <t 1228180882, conn 1699837157> executing prepstmnt 2127861376 SELECT t0.nombre FROM Compania t0 WHERE t0.id = ? [params=(int) 1]
497 testMySql TRACE [http-bio-8080-exec-5] openjpa.jdbc.SQL - <t 1228180882, conn 1699837157> [15 ms] spent
As you can see, there is no t0.id in the select.
Thanks for your help.

Primary Key (ID) not retrieved (?) from database using OpenJPA
Duplicate.... the net of the post is that you need to use a different enhancement method.

If you don't specifically set the value for the #Id attribute you have to declare it with #GeneratedValueso that it's automatically incremented.

Related

Hibernate JPA DB2 Foreign key based on composite unique key

I have 2 tables parent and child, parent as 1 Primary Key and a composite unique key(Combination of 2 columns[UN_KEY1, UN_KEY2]) . Now in the child table i refer these 2 columns as foreign keys. When i try to generate the entity in eclipse it show Many to one relationship and displays the parent columns. But when i generate these two columns are not generated in the Parent Entity. How to do transaction like add, update, delete in these entity without those columns
Table
--drop table "TBL_PARENT";
CREATE TABLE "TBL_PARENT"(
"S_ID" INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY(START WITH 1, INCREMENT BY 1, NO MINVALUE, NO MAXVALUE, CACHE 20),
"UN_KEY1" Integer NOT NULL,
"UN_KEY2" Smallint NOT NULL,
"SOME_COL1" Integer
);
-- Add keys for table TBL_PARENT
ALTER TABLE "TBL_PARENT" ADD CONSTRAINT "TBL_PARENTKEY3" PRIMARY KEY ("S_ID");
ALTER TABLE "TBL_PARENT" ADD CONSTRAINT "TBL_PARENTKey4" UNIQUE ("UN_KEY1","UN_KEY2");
--drop table "TBL_PARENT";
CREATE TABLE "TBL_CHILD"(
"S_ID" Integer NOT NULL GENERATED ALWAYS AS IDENTITY(START WITH 1, INCREMENT BY 1, NO MINVALUE, NO MAXVALUE, CACHE 20),
"UN_KEY1" Integer,
"UN_KEY2" Integer,
"SOME_COL2" Integer
);
ALTER TABLE "TBL_CHILD" ADD CONSTRAINT "TBL_CHILD_KEY3" PRIMARY KEY ("S_ID");
ALTER TABLE "TBL_CHILD" ADD CONSTRAINT "TBL_CHILD_FK" FOREIGN KEY ("UN_KEY1", "UN_KEY2") REFERENCES "TBL_PARENT" ("UN_KEY1", "UN_KEY2");
Generated Code:
#Entity
#Table(name="TBL_PARENT")
#NamedQuery(name="TblParent.findAll", query="SELECT t FROM TblParent t")
public class TblParent implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name="S_ID")
private int sId;
#Column(name="SOME_COL1")
private int someCol1;
//bi-directional many-to-one association to TblChild
#OneToMany(mappedBy="tblParent")
private Set<TblChild> tblChilds;
public TblParent() {
}
public int getSId() {
return this.sId;
}
public void setSId(int sId) {
this.sId = sId;
}
public int getSomeCol1() {
return this.someCol1;
}
public void setSomeCol1(int someCol1) {
this.someCol1 = someCol1;
}
public Set<TblChild> getTblChilds() {
return this.tblChilds;
}
public void setTblChilds(Set<TblChild> tblChilds) {
this.tblChilds = tblChilds;
}
public TblChild addTblChild(TblChild tblChild) {
getTblChilds().add(tblChild);
tblChild.setTblParent(this);
return tblChild;
}
public TblChild removeTblChild(TblChild tblChild) {
getTblChilds().remove(tblChild);
tblChild.setTblParent(null);
return tblChild;
}
}
#Entity
#Table(name="TBL_CHILD")
#NamedQuery(name="TblChild.findAll", query="SELECT t FROM TblChild t")
public class TblChild implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name="S_ID")
private int sId;
#Column(name="SOME_COL2")
private int someCol2;
//bi-directional many-to-one association to TblParent
#ManyToOne
#JoinColumns({
#JoinColumn(name="UN_KEY1", referencedColumnName="UN_KEY1"),
#JoinColumn(name="UN_KEY2", referencedColumnName="UN_KEY2")
})
private TblParent tblParent;
public TblChild() {
}
public int getSId() {
return this.sId;
}
public void setSId(int sId) {
this.sId = sId;
}
public int getSomeCol2() {
return this.someCol2;
}
public void setSomeCol2(int someCol2) {
this.someCol2 = someCol2;
}
public TblParent getTblParent() {
return this.tblParent;
}
public void setTblParent(TblParent tblParent) {
this.tblParent = tblParent;
}
}
Add the following to TblParent object
#Column(name = "UN_KEY1")
private int uniqueKey1;
#Column(name = "UN_KEY2")
private int uniqueKey2;
When creating a new object you will be doing the following
TblParent p = new TblParent();
p.setSId(1);
p.setSomeCol1(12);
p.setUniqueKey1(12);
p.setUniqueKey2(14);
p.setTblChilds(new HashSet<TblChild>());
TblChild c = new TblChild();
c.setSId(1);
c.setSomeCol2(14);
c.setTblParent(p);
p.getTblChilds.add(c);
When you create this parent object the framework will automatically add the foreign key values to TblChild table.

one to many hibernate

Hi I am trying to do one to many insert but I am having problems.
I have two tables:
CREATE TABLE users_app (
user_id int UNSIGNED NOT NULL AUTO_INCREMENT,
user_number varchar(45) NOT NULL default '0',
user_password varchar(45) NOT NULL default '0',
os int(1) unsigned NOT NULL,
token varchar(500) NOT NULL,
PRIMARY KEY (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8;
CREATE TABLE user_app_devices(
id int AUTO_INCREMENT PRIMARY KEY,
user_id int UNSIGNED NOT NULL,
device_name varchar(45) NOT NULL,
FOREIGN KEY (user_id) REFERENCES users_app (user_id)
)ENGINE=InnoDB CHARSET=utf8;
My classes:
#Entity
#Table(name="user_app_devices")
public class UserAppDevice implements Serializable {
private static final long serialVersionUID = 1L;
#Id
private int id;
#Column(name="device_name")
private String deviceName;
//bi-directional many-to-one association to UsersApp
#ManyToOne
#JoinColumn(name="user_id")
private UsersApp usersApp;
public UserAppDevice() {
}
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
public String getDeviceName() {
return this.deviceName;
}
public void setDeviceName(String deviceName) {
this.deviceName = deviceName;
}
public UsersApp getUsersApp() {
return this.usersApp;
}
public void setUsersApp(UsersApp usersApp) {
this.usersApp = usersApp;
}
}
#Entity
#Table(name="users_app")
public class UsersApp implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name="user_id")
private int userId;
private int os;
private String token;
#Column(name="user_number")
private String userNumber;
#Column(name="user_password")
private String userPassword;
//bi-directional many-to-one association to UserAppDevice
#OneToMany(mappedBy="usersApp")
private List<UserAppDevice> userAppDevices;
public UsersApp() {
}
public int getUserId() {
return this.userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public int getOs() {
return this.os;
}
public void setOs(int os) {
this.os = os;
}
public String getToken() {
return this.token;
}
public void setToken(String token) {
this.token = token;
}
public String getUserNumber() {
return this.userNumber;
}
public void setUserNumber(String userNumber) {
this.userNumber = userNumber;
}
public String getUserPassword() {
return this.userPassword;
}
public void setUserPassword(String userPassword) {
this.userPassword = userPassword;
}
public List<UserAppDevice> getUserAppDevices() {
return this.userAppDevices;
}
public void setUserAppDevices(List<UserAppDevice> userAppDevices) {
this.userAppDevices = userAppDevices;
}
public UsersApp(int os, String token, String userNumber, String userPassword) {
this.os = os;
this.token = token;
this.userNumber = userNumber;
this.userPassword = userPassword;
}
I want to add new user with device
I try this code:
Session session = (Session) em.getDelegate();
session.beginTransaction();
UsersApp user = new UsersApp(os, token, userNumber, userPassword);
session.save(user);
UserAppDevice ud = new UserAppDevice();
ud.setUsersApp(user);
ud.setDeviceName(device);
session.save(ud);
session.getTransaction().commit();
but I am facing exception:
13:16:48,516 WARN [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (http--0.0.0.0-8080-3) SQL Error: 1452, SQLState: 23000
13:16:48,517 ERROR [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (http--0.0.0.0-8080-3) Cannot add or update a child row: a foreign key constraint fails (`application`.`user_a
pp_devices`, CONSTRAINT `user_app_devices_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users_app` (`user_id`))
13:16:48,520 ERROR [org.jboss.as.ejb3.tx.CMTTxInterceptor] (http--0.0.0.0-8080-3) javax.ejb.EJBTransactionRolledbackException: Cannot add or update a child row: a foreign key const
raint fails (`application`.`user_app_devices`, CONSTRAINT `user_app_devices_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users_app` (`user_id`))
13:16:48,524 ERROR [org.jboss.ejb3.invocation] (http--0.0.0.0-8080-3) JBAS014134: EJB Invocation failed on component DeviceRegisterDAOImpl for method public abstract void com.break
id.ejb.model.DeviceRegisterDAO.add(int,java.lang.String,java.lang.String,java.lang.String,java.lang.String): javax.ejb.EJBTransactionRolledbackException: Cannot add or update a chi
ld row: a foreign key constraint fails (`application`.`user_app_devices`, CONSTRAINT `user_app_devices_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users_app` (`user_id`))
at org.jboss.as.ejb3.tx.CMTTxInterceptor.handleInCallerTx(CMTTxInterceptor.java:139) [jboss-as-ejb3-7.1.1.Final.jar:7.1.1.Final]
at org.jboss.as.ejb3.tx.CMTTxInterceptor.invokeInCallerTx(CMTTxInterceptor.java:204) [jboss-as-ejb3-7.1.1.Final.jar:7.1.1.Final]
at org.jboss.as.ejb3.tx.CMTTxInterceptor.required(CMTTxInterceptor.java:306) [jboss-as-ejb3-7.1.1.Final.jar:7.1.1.Final]
at org.jboss.as.ejb3.tx.CMTTxInterceptor.processInvocation(CMTTxInterceptor.java:190) [jboss-as-ejb3-7.1.1.Final.jar:7.1.1.Final]
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:288) [jboss-invocation-1.1.1.Final.jar:1.1.1.Final]
at org.jboss.as.ejb3.remote.EJBRemoteTransactionPropagatingInterceptor.processInvocation(EJBRemoteTransactionPropagatingInterceptor.java:80) [jboss-as-ejb3-7.1.1.Final.jar:
7.1.1.Final]
What am I missing ?
You haven't told Hibernate that the ID of UserApp was generated automatically by the database:
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name="user_id")
private int userId;
(and do the same for the other entity)
Since your are using bidirectional, change your client code as below.
Session session = (Session) em.getDelegate();
session.beginTransaction();
UserAppDevice ud = new UserAppDevice();
ud.setDeviceName(device);
UsersApp user = new UsersApp(os, token, userNumber, userPassword);
user.setUserAppDevices(new ArrayList<UserAppDevice>())
user.getUserAppDevices().add(ud);
session.save(user);
session.getTransaction().commit();
As mentioned by JB Nizet, you're missing the autogenerated strategy.
An alternative would be to use UUID as your id column and create the values yourself with
#Id
private UUID id = UUID.randomUUID();
Also, don't forget to set equals/hashCode to use the id field as discussed to death in The JPA hashCode() / equals() dilemma
Incidentally, why are you using Session (hibernate specific) instead of sticking to JPA's API?

Hibernate: Transfer seeming n:n mapping in Database to #OneToMany in Hibernate with additional condition

I have a Database with a Mapping between applications and application_descriptions. Every application could have more than one description (mapped by column product_id). Column product_id in table applications can have duplicate values, but combinations of column product_id and column wrapping_version are unique. So the descriptions should only map to the application with highest version.
I have worked out a #OneToMany mapping in table application to get all descriptions. In descriptions I only get the String of product_id. That’s not optimal, but it doesn’t work to map it like in alternative a).
So the solution I have made worked fine for reading data from database, but when I try to update an application to database I get (only sometimes) following error:
Hibernate:
/* update
com.twistbox.iwp.dao.Application */ update
applications
set
created=?,
design_id=?,
message=?,
product_id=?,
product_title=?,
retailer_id=?,
state=?,
tbyb_playduration=?,
tbyb_startups=?,
wrapping_security_layer=?,
wrapping_version=?
where
id=?
Hibernate:
/* delete one-to-many com.twistbox.iwp.dao.Application.applicationDescriptions */ update
application_descriptions
set
product_id=null
where
product_id=?
104330 [http-8080-1] WARN org.hibernate.util.JDBCExceptionReporter - SQL Error: 1048, SQLState: 23000
104330 [http-8080-1] ERROR org.hibernate.util.JDBCExceptionReporter - Column 'product_id' cannot be null
I have tried
1. to set the mapped description set to null before updating
2. set to a new empty HashSet Object before updating
3. let the mapped object like I get it from database
On default hibernate shouldn’t cascade on update and I haven’t found a way to stop doing it (last try was #OneToMany(cascade = {})). I have also tried in both tables true and false values for:
1. attribute null-able
2. updateable
3. insertable
Some of them worked for the application I got the error, but then I get same error for other applications witch only works if I remove the attributes again. Any ideas what to do?
My code (only important getter and setter, all other removed for better overview):
#Entity
#Table (name = "applications")
#FilterDef(name = "versionFilter")
public class Application implements Comparable<Application>, Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private long id;
private Retailer retailerId;
private long designId;
private String productId;
private String productTitle;
private int tbybPlayDuration;
private int tbybStartups;
private int wrappingSecurityLayer;
private int wrappingVersion;
private ApplicationStatus status;
private String message;
private Timestamp created;
private Set<ApplicationDescription> applicationDescriptions = new HashSet<ApplicationDescription>();
private Set<PricingApplicationMapping> pricingApplication = new HashSet<PricingApplicationMapping>();
public Application() {
}
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#GenericGenerator(name="increment", strategy="increment")
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
#Column(name="product_id")
public String getProductId() {
return productId;
}
public void setProductId(String productId) {
this.productId = productId;
}
#OneToMany(cascade = {})
#JoinColumn(name="product_id", referencedColumnName="product_id")
#Filter(name = "versionFilter", condition = "wrapping_version =select max(A.wrapping_version) from application A where A.product_id= product_id")
public Set<ApplicationDescription> getApplicationDescriptions() {
return applicationDescriptions;
}
public void setApplicationDescriptions(
Set<ApplicationDescription> applicationDescriptions) {
this.applicationDescriptions = applicationDescriptions;
}
#Override
public int compareTo(Application o) {
return this.getProductTitle().compareToIgnoreCase(o.getProductTitle());
}
}
#Entity
#Table (name = "application_descriptions")
#FilterDef(name = "paMapping")
public class ApplicationDescription implements Comparable<ApplicationDescription>, Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private long id;
private String productId;
// private Application application;
// private String countryCode;
private Territory territory;
private String name;
private String description;
private String termsAndConditions;
public ApplicationDescription() {
}
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#GenericGenerator(name="increment", strategy="increment")
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
// #ManyToOne
// #JoinColumn(name="product_id")
// public Application getApplication() {
// return application;
// }
//
// public void setApplication(Application application) {
// this.application = application;
// }
#Column(name="product_id")
public String getProductId() {
return productId;
}
public void setProductId(String productId) {
this.productId = productId;
}
#Column(name="name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Column(name="description")
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
#Column(name="terms_and_conditions")
public String getTermsAndConditions() {
if (this.termsAndConditions != null && !this.termsAndConditions.equals("") && !this.termsAndConditions.toLowerCase().equals("null"))
return this.termsAndConditions;
return "default";
}
public void setTermsAndConditions(String termsAndConditions) {
this.termsAndConditions = termsAndConditions;
}
#JoinColumn(name="country_code")
#OneToOne
public Territory getTerritory() {
return territory;
}
public void setTerritory(Territory territory) {
this.territory = territory;
}
#Override
public int compareTo(ApplicationDescription o) {
return this.getTerritory().getCountryCode().compareToIgnoreCase(o.getTerritory().getCountryCode());
}
}
Alternative for product_id in application_descriptions a):
#ManyToOne
#JoinColumn(name="product_id")
public Application getApplication() {
return application;
}
Error Message:
Hibernate:
/* load one-to-many com.twistbox.iwp.dao.Application.applicationDescriptions */ select
applicatio0_.product_id as product5_0_2_,
applicatio0_.id as id2_,
applicatio0_.id as id4_1_,
applicatio0_.product_id as product5_4_1_,
applicatio0_.description as descript2_4_1_,
applicatio0_.name as name4_1_,
applicatio0_.terms_and_conditions as terms4_4_1_,
applicatio0_.country_code as country6_4_1_,
territory1_.country_code as country1_8_0_,
territory1_.currency as currency8_0_,
territory1_.name as name8_0_,
territory1_.terms_and_conditions as terms4_8_0_
from
application_descriptions applicatio0_
left outer join
territories territory1_
on applicatio0_.country_code=territory1_.country_code
where
applicatio0_.product_id=?
180684 [http-8080-1] WARN org.hibernate.util.JDBCExceptionReporter - SQL Error: 0, SQLState: S1009
180684 [http-8080-1] ERROR org.hibernate.util.JDBCExceptionReporter - Invalid value for getLong() - 'para'
SQL generating tables:
CREATE TABLE IF NOT EXISTS `applications` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`retailer_id` int(10) unsigned NOT NULL,
`design_id` int(10) unsigned NOT NULL,
`product_id` varchar(150) NOT NULL,
`product_title` varchar(150) NOT NULL,
`tbyb_playduration` int(10) NOT NULL,
`tbyb_startups` int(10) NOT NULL,
`wrapping_security_layer` int(10) unsigned NOT NULL DEFAULT '1',
`wrapping_version` int(10) unsigned NOT NULL DEFAULT '1',
`state` enum('WAITING','RUNNING','DONE','FAILED') NOT NULL DEFAULT 'WAITING',
`message` varchar(250) DEFAULT NULL,
`created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `product_id_wrapping_version` (`product_id`,`wrapping_version`),
KEY `FK_applications_retailers` (`retailer_id`),
KEY `FK_applications_custom_designs` (`design_id`),
KEY `product_id` (`product_id`),
CONSTRAINT `FK_applications_custom_designs` FOREIGN KEY (`design_id`) REFERENCES `custom_designs` (`id`),
CONSTRAINT `FK_applications_retailers` FOREIGN KEY (`retailer_id`) REFERENCES `retailers` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `application_descriptions` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`product_id` varchar(150) NOT NULL,
`country_code` varchar(5) NOT NULL,
`name` varchar(150) NOT NULL,
`description` varchar(500) NOT NULL,
`terms_and_conditions` text,
PRIMARY KEY (`id`),
UNIQUE KEY `product_id_county_code` (`product_id`,`country_code`),
KEY `FK_application_descriptions_applications` (`product_id`),
KEY `FK_application_descriptions_territories` (`country_code`),
CONSTRAINT `FK_application_descriptions_territories` FOREIGN KEY (`country_code`) REFERENCES `territories` (`country_code`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Application update:
public static long updateApplication(Application application){
SessionFactory sf = HibernateUtil.getSessionFactory();
Session session = null;
try{
session = sf.openSession();
session.beginTransaction();
session.saveOrUpdate(application);
session.getTransaction().commit();
}
catch(HibernateException he){
logger.severe("Error updating application! " + he.getMessage() + " " + he.getStackTrace());
return -1;
}
catch(Exception e){
logger.severe("Error updating application! " + e.getMessage() + " " + e.getStackTrace());
return -1;
}
finally{
session.close();
}
return application.getId();
}

How to Represent Composite keys in Hibernate using Annotations?

So I reverse engineered some tables from my db and when I try to save my object to the db I get the following error:
Initial SessionFactory creation failed.org.hibernate.AnnotationException: A Foreign key refering com.mycode.Block from com.mycode.Account has the wrong number of column. should be 2
Exception in thread "main" java.lang.ExceptionInInitializerError
The Domain objects Are Block which contains a number of Account Objects:
#OneToMany(fetch = FetchType.LAZY, mappedBy = "Block")
public Set<EAccount> getAccounts() {
return this.Accounts;
}
Account has a Composite key of Id and Role. This has been setup in a seperate Class:
#Embeddable
public class BlockAccountId implements java.io.Serializable {
private long blockOid;
private String accountRole;
public BlockAccountId() {
}
public BlockAccountId(long blockOid, String accountRole) {
this.blockOid = blockOid;
this.accountRole = accountRole;
}
#Column(name = "BLOCK_OID", nullable = false)
public long getBlockOid() {
return this.blockOid;
}
public void setBlockOid(long blockOid) {
this.blockOid = blockOid;
}
#Column(name = "ACCOUNT_ROLE", nullable = false, length = 10)
public String getAccountRole() {
return this.accountRole;
}
public void setAccountRole(String accountRole) {
this.accountRole = accountRole;
}
So I want to know. How can I Link the tables Block and account on blockOid but still ensure the account table has both blockOid and accountRole as a composite key.
Any examples would be greatly appreciated!
N.B this is a Block (One) to Account (Many) relationship.
Thanks
The easiest is to place your association directly in the embedded id component.
Hibernate reference documentation
Section 5.1.2.1.1. id as a property using a component type ()
Example (Only write the important getter() and setter())
#Entity
public class Block {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="BLOCK_OID")
long blockOid;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "id.block", cascade=CascadeType.ALL)
Set<Account> accounts = new HashSet<Account>();
}
#Entity
public class Account {
#EmbeddedId BlockAccountId id;
public Account()
{
this.id = new BlockAccountId();
}
public void setBlock(Block pBlock) {
this.id.setBlock(pBlock);
}
public Block getBlock() {
return this.id.getBlock();
}
public String getAccountRole() {
return this.id.getAccountRole();
}
public void setAccountRole(String accountRole) {
this.id.setAccountRole(accountRole);
}
}
#Embeddable
public class BlockAccountId implements java.io.Serializable {
#ManyToOne(optional = false)
private Block block;
#Column(name = "ACCOUNT_ROLE", nullable = false, length = 10)
private String accountRole;
public BlockAccountId() {
}
//Implement equals and hashcode
}
The corresponding database table are :
CREATE TABLE block (
BLOCK_OID bigint(20) NOT NULL auto_increment,
PRIMARY KEY (`BLOCK_OID`)
)
CREATE TABLE account (
ACCOUNT_ROLE varchar(10) NOT NULL,
block_BLOCK_OID bigint(20) NOT NULL,
PRIMARY KEY (`ACCOUNT_ROLE`,`block_BLOCK_OID`),
KEY `FK_block_OID` (`block_BLOCK_OID`),
CONSTRAINT `FK_block_OID` FOREIGN KEY (`block_BLOCK_OID`) REFERENCES `block` (`BLOCK_OID`)
)
based on hibernate documentation here's the link
based on it you can do the following :
#Entity
public class Account {
#EmbeddedId BlockAccountId id;
#MapsId(value = "blockOid")
#ManyToOne
private Block block;
public Account()
{
this.id = new BlockAccountId();
}
public void setBlock(Block pBlock) {
this.block = pBlock;
}
public Block getBlock() {
return this.block;
}
public String getAccountRole() {
return this.id.getAccountRole();
}
public void setAccountRole(String accountRole) {
this.id.setAccountRole(accountRole);
}
}

Java Hibernate - Composite Primary Key Issue

I have following two tables
CREATE TABLE event_type_master (
Event_Type_Code varchar(128) NOT NULL,
PRIMARY KEY (Event_Type_Code)
)
CREATE TABLE event_master (
Event_Code varchar(128) NOT NULL,
Event_Type_Code varchar(128) NOT NULL,
PRIMARY KEY (Event_Code,Event_Type_Code),
CONSTRAINT FK1 FOREIGN KEY (Event_Type_Code) REFERENCES event_type_master (Event_Type_Code)
)
Now I have create model classes for the above relation as follow
EventMaster Class:-
#Entity
#Table(name="event_master")
public class EventMaster implements java.io.Serializable {
private EventMasterId id;
private EventTypeMaster eventTypeMaster;
private String eventName;
public EventMaster() {
}
public EventMaster(EventMasterId id, EventTypeMaster eventTypeMaster) {
this.id = id;
this.eventTypeMaster = eventTypeMaster;
}
public EventMaster(EventMasterId id, EventTypeMaster eventTypeMaster) {
this.id = id;
this.eventTypeMaster = eventTypeMaster;
this.eventName = eventName;
}
#EmbeddedId
#AttributeOverrides( {
#AttributeOverride(name="eventCode", column=#Column(name="Event_Code", nullable=false, length=128) ),
#AttributeOverride(name="eventTypeCode", column=#Column(name="Event_Type_Code", nullable=false, length=128) ) } )
public EventMasterId getId() {
return this.id;
}
public void setId(EventMasterId id) {
this.id = id;
}
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="Event_Type_Code",referencedColumnName = "Event_Type_Code", nullable=false, insertable=false, updatable=false)
public EventTypeMaster getEventTypeMaster()
{
return this.eventTypeMaster;
}
public void setEventTypeMaster(EventTypeMaster eventTypeMaster) {
this.eventTypeMaster = eventTypeMaster;
}
}
EventMasterId Class for Compound Primary Key setting:-
#Embeddable
public class EventMasterId implements java.io.Serializable {
private String eventCode;
private String eventTypeCode;
public EventMasterId() {
}
public EventMasterId(String eventCode, String eventTypeCode)
{
this.eventCode = eventCode;
this.eventTypeCode = eventTypeCode;
}
#Column(name="Event_Code", nullable=false, length=128)
public String getEventCode() {
return this.eventCode;
}
public void setEventCode(String eventCode) {
this.eventCode = eventCode;
}
#Column(name="Event_Type_Code", nullable=false, length=128)
public String getEventTypeCode() {
return this.eventTypeCode;
}
public void setEventTypeCode(String eventTypeCode) {
this.eventTypeCode = eventTypeCode;
}
public boolean equals(Object other) {
........
}
public int hashCode() {
..........
}
}
EventTypeMaster Class
#Entity
#Table(name="event_type_master")
public class EventTypeMaster implements java.io.Serializable {
private String eventTypeCode;
private String eventTypeName;
private Set<EventMaster> eventMasters = new HashSet<EventMaster>(0);
public EventTypeMaster() {
}
public EventTypeMaster(String eventTypeCode) {
this.eventTypeCode = eventTypeCode;
}
public EventTypeMaster(String eventTypeCode, String eventTypeName, Set eventMasters) {
this.eventTypeCode = eventTypeCode;
this.eventTypeName = eventTypeName;
this.eventMasters = eventMasters;
}
#Id
#Column(name="Event_Type_Code", unique=true, nullable=false, length=128)
public String getEventTypeCode() {
return this.eventTypeCode;
}
public void setEventTypeCode(String eventTypeCode) {
this.eventTypeCode = eventTypeCode;
}
#OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="eventTypeMaster")
#JoinColumn(name="Event_Type_Code", referencedColumnName = "Event_Type_Code")
public Set<EventMaster> getEventMasters() {
return this.eventMasters;
}
public void setEventMasters(Set<EventMaster> eventMasters) {
this.eventMasters = eventMasters;
}
}
After setting All I created a HebernateUtil Class using Netbeans to connect to HibernateSession Factory and tried to Test adding a record to event_master table as follow
Session session = null;
session = NewHibernateUtil.getSessionFactory().getCurrentSession();
try {
org.hibernate.Transaction tx = session.beginTransaction();
EventMasterId key1=new EventMasterId();
EventTypeMaster eTypeMaster1=new EventTypeMaster();
eTypeMaster1=(EventTypeMaster)session.load(EventTypeMaster.class, "e1");
key1.setEventCode(eTypeMaster1.getEventTypeCode());
key1.setEventCode("Test_Event_Code");
EventMaster em=new EventMaster();
em.setId(key1);
em.setEventTypeMaster(eTypeMaster1);
em.setEventDesc("Event Description");
session.save(em);
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
}
But I am getting following Error
Hibernate: insert into event_master (Create_DTTM, Created_By, Event_Desc, Event_Name, Event_Short_Name, Last_Mod_By, Last_Mod_DTTM, Event_Code, Event_Type_Code) values (?, ?, ?, ?, ?, ?, ?, ?, ?)
1473 [main] WARN org.hibernate.util.JDBCExceptionReporter - SQL Error: 1048, SQLState: 23000
1473 [main] ERROR org.hibernate.util.JDBCExceptionReporter - Column 'Event_Type_Code' cannot be null
1474 [main] ERROR org.hibernate.event.def.AbstractFlushingEventListener - Could not synchronize database state with session
org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:94)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:275)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:266)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:167)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1028)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:366)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:137)
at test.NewMain.main(NewMain.java:46)
Caused by: java.sql.BatchUpdateException: Column 'Event_Type_Code' cannot be null
at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:1666)
at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:1082)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268)
Please help me to solve this.
I think you have a typo.
key1.setEventCode(eTypeMaster1.getEventTypeCode());
key1.setEventCode("Test_Event_Code");
Should the first line be key1.setEventTypeCode.

Categories

Resources