Hibernate mapping one-to-many problem - java

I am not very experienced with Hibernate and I am trying to create one-to-many mapping.
Here are relevant tables:
And here are my mapping files:
<hibernate-mapping package="com.xorty.mailclient.server.domain">
<class name="Attachment" table="Attachment">
<id name="id">
<column name="idAttachment"></column>
</id>
<property name="filename">
<column name="name"></column>
</property>
<property name="blob">
<column name="file"></column>
<type name="blob"></type>
</property>
<property name="mailId">
<column name="mail_idmail"></column>
</property>
</class>
</hibernate-mapping>
<hibernate-mapping>
<class name="com.xorty.mailclient.server.domain.Mail" table="mail">
<id name="id" type="integer" column="idmail"></id>
<property name="content">
<column name="body"></column>
</property>
<property name="ownerAddress">
<column name="account_address"></column>
</property>
<property name="title">
<column name="head"></column>
</property>
<set name="receivers" table="mail_has_contact" cascade="all">
<key column="mail_idmail"></key>
<many-to-many column="contact_address" class="com.xorty.mailclient.client.domain.Contact"></many-to-many>
</set>
<bag name="attachments" cascade="save-update, delete" inverse="true">
<key column="mail_idmail" not-null="true"/>
<one-to-many class="com.xorty.mailclient.server.domain.Attachment"/>
</bag>
</class>
</hibernate-mapping>
In plain english, one mail has more attachments.
When I try to do CRUD on mail without attachments, everyting works just fine. When I add some attachment to mail, I cannot perform any CRUD operation.
I end up with following trace:
org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:96)
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:268)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:184)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1216)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:383)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:133)
at domain.DatabaseTest.testPersistMailWithAttachment(DatabaseTest.java:355)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at junit.framework.TestCase.runTest(TestCase.java:168)
at junit.framework.TestCase.runBare(TestCase.java:134)
at junit.framework.TestResult$1.protect(TestResult.java:110)
at junit.framework.TestResult.runProtected(TestResult.java:128)
at junit.framework.TestResult.run(TestResult.java:113)
at junit.framework.TestCase.run(TestCase.java:124)
at junit.framework.TestSuite.runTest(TestSuite.java:232)
at junit.framework.TestSuite.run(TestSuite.java:227)
at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:83)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: java.sql.BatchUpdateException: Cannot add or update a child row: a foreign key constraint fails (`maildb`.`attachment`, CONSTRAINT `fk_Attachment_mail1` FOREIGN KEY (`mail_idmail`) REFERENCES `mail` (`idmail`) ON DELETE NO ACTION ON UPDATE NO ACTION)
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)
... 27 more
Thank you
EDIT: On hvgotcodes proposal:
package com.xorty.mailclient.server.domain;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import com.xorty.mailclient.client.domain.Account;
import com.xorty.mailclient.client.domain.AttachmentDTO;
import com.xorty.mailclient.client.domain.Contact;
import com.xorty.mailclient.client.domain.MailDTO;
/**
* Heavy weight Hibernate Mail
* #author MisoV
* #version 0.1
*/
public class Mail implements Serializable {
private List<Attachment> attachments = new ArrayList<Attachment>();
private String content;
private int id;
private boolean isNew;
private Account owner;
private String ownerAddress;
private Set<Contact> receivers = new HashSet<Contact>();
private String sender;
private String title;
/**
* Hibernate purposes
*/
public Mail() { // $codepro.audit.disable
}
/**
* Unwraps light DTO object to heavy Hibernate object.
* #param dto Corresponding DTO class.
*/
public Mail(final MailDTO dto) {
for (final AttachmentDTO attachmentDTO : dto.getAttachments()) {
attachments.add(new Attachment(attachmentDTO));
}
content = dto.getContent();
id = dto.getId();
isNew = dto.isNew();
owner = dto.getOwner();
ownerAddress = dto.getOwnerAddress();
receivers = dto.getReceivers();
sender = dto.getSender();
title = dto.getTitle();
}
/**
* Inserts new attachment
* #param attachment
*/
public void addAttachment(final Attachment attachment) {
attachments.add(attachment);
}
/* (non-Javadoc)
* #see java.lang.Object#equals(java.lang.Object)
*/
#Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof Mail)) {
return false;
}
final Mail other = (Mail) obj;
if (attachments == null) {
if (other.attachments != null) {
return false;
}
} else if (!attachments.equals(other.attachments)) {
return false;
}
if (content == null) {
if (other.content != null) {
return false;
}
} else if (!content.equals(other.content)) {
return false;
}
if (id != other.id) {
return false;
}
if (isNew != other.isNew) {
return false;
}
if (owner == null) {
if (other.owner != null) {
return false;
}
} else if (!owner.equals(other.owner)) {
return false;
}
if (ownerAddress == null) {
if (other.ownerAddress != null) {
return false;
}
} else if (!ownerAddress.equals(other.ownerAddress)) {
return false;
}
if (receivers == null) {
if (other.receivers != null) {
return false;
}
} else if (!receivers.equals(other.receivers)) {
return false;
}
if (sender == null) {
if (other.sender != null) {
return false;
}
} else if (!sender.equals(other.sender)) {
return false;
}
if (title == null) {
if (other.title != null) {
return false;
}
} else if (!title.equals(other.title)) {
return false;
}
return true;
}
/**
* #return the attachments
*/
public List<Attachment> getAttachments() {
return attachments;
}
/**
* #return the content
*/
public String getContent() {
return content;
}
/**
* #return the id
*/
public int getId() {
return id;
}
/**
* #return the owner
*/
public Account getOwner() {
return owner;
}
/**
* #return the ownerAddress
*/
public String getOwnerAddress() {
return ownerAddress;
}
/**
* #return the receivers
*/
public Set<Contact> getReceivers() {
return receivers;
}
/**
* #return the sender
*/
public String getSender() {
return sender;
}
/**
* #return the title
*/
public String getTitle() {
return title;
}
/* (non-Javadoc)
* #see java.lang.Object#hashCode()
*/
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((attachments == null) ? 0 : attachments.hashCode());
result = prime * result + ((content == null) ? 0 : content.hashCode());
result = prime * result + id;
result = prime * result + (isNew ? 1231 : 1237);
result = prime * result + ((owner == null) ? 0 : owner.hashCode());
result = prime * result
+ ((ownerAddress == null) ? 0 : ownerAddress.hashCode());
result = prime * result
+ ((receivers == null) ? 0 : receivers.hashCode());
result = prime * result + ((sender == null) ? 0 : sender.hashCode());
result = prime * result + ((title == null) ? 0 : title.hashCode());
return result;
}
/**
* #return the isNew
*/
public boolean isNew() {
return isNew;
}
/**
* #param attachments the attachments to set
*/
public void setAttachments(final List<Attachment> attachments) {
this.attachments = attachments;
}
/**
* #param content the content to set
*/
public void setContent(final String content) {
this.content = content;
}
/**
* #param id the id to set
*/
public void setId(final int id) {
this.id = id;
}
/**
* #param isNew the isNew to set
*/
public void setNew(final boolean isNew) {
this.isNew = isNew;
}
/**
* #param owner the owner to set
*/
public void setOwner(final Account owner) {
this.owner = owner;
}
/**
* #param ownerAddress the ownerAddress to set
*/
public void setOwnerAddress(final String ownerAddress) {
this.ownerAddress = ownerAddress;
}
/**
* #param receivers the receivers to set
*/
public void setReceivers(final Set<Contact> receivers) {
this.receivers = receivers;
}
/**
* #param sender the sender to set
*/
public void setSender(final String sender) {
this.sender = sender;
}
/**
* #param title the title to set
*/
public void setTitle(final String title) {
this.title = title;
}
}
Attachment:
// $codepro.audit.disable com.instantiations.assist.eclipse.analysis.audit.rule.effectivejava.alwaysOverridetoString.alwaysOverrideToString
/**
*
*/
package com.xorty.mailclient.server.domain;
import java.io.Serializable;
import java.sql.SQLException;
import javax.sql.rowset.serial.SerialBlob;
import javax.sql.rowset.serial.SerialException;
import com.xorty.mailclient.client.domain.AttachmentDTO;
/**
* Heavy weight Hibernate Attachment
* #author MisoV
* #version 0.1
*/
public class Attachment implements Serializable {
private static final long serialVersionUID = 2047475939737947104L;
private SerialBlob blob;
private byte[] content;
private String contentid;
private String contenttype;
private String filename;
private int id;
private int mailId;
/**
* Hibernate purposes
*/
public Attachment() { // $codepro.audit.disable emptyMethod
}
/**
* Unwraps DTO to heavy weight hibernate object.
* #param dto
*/
public Attachment(final AttachmentDTO dto) {
content = dto.getContent();
contentid = dto.getContentid();
contenttype = dto.getContenttype();
filename = dto.getFilename();
id = dto.getId();
mailId = dto.getMailId();
try {
blob = new SerialBlob(content);
} catch (final SerialException e) {
e.printStackTrace();
} catch (final SQLException e) {
e.printStackTrace();
}
}
/**
* #return the blob
*/
public SerialBlob getBlob() {
return blob;
}
/**
* #return the content
*/
public byte[] getContent() {
return content;
}
/**
* #return the contentid
*/
public String getContentid() {
return contentid;
}
/**
* #return the contenttype
*/
public String getContenttype() {
return contenttype;
}
/**
* #return the filename
*/
public String getFilename() {
return filename;
}
/**
* #return the id
*/
public int getId() {
return id;
}
/**
* #return the mailId
*/
public int getMailId() {
return mailId;
}
/**
* #param blob the blob to set
*/
public void setBlob(final SerialBlob blob) {
this.blob = blob;
}
/**
* #param content the content to set
*/
public void setContent(final byte[] content) {
this.content = content;
}
/**
* #param contentid the contentid to set
*/
public void setContentid(final String contentid) {
this.contentid = contentid;
}
/**
* #param contenttype the contenttype to set
*/
public void setContenttype(final String contenttype) {
this.contenttype = contenttype;
}
/**
* #param filename the filename to set
*/
public void setFilename(final String filename) {
this.filename = filename;
}
/**
* #param id the id to set
*/
public void setId(final int id) {
this.id = id;
}
/**
* #param mailId the mailId to set
*/
public void setMailId(final int mailId) {
this.mailId = mailId;
}
}
EDIT2:
Hibernate actually performs insert:
insert into Attachment (name, file, mail_idmail, idAttachment) values (?, ?, ?, ?)
And values are correctly set. It doesn't fail on session.save nor on session.get (it even gets correct copy). It fails on committing transaction.
Only thing I can get of it is: Cannot add or update a child row: a foreign key constraint fails (maildb.attachment, CONSTRAINTfk_Attachment_mail1FOREIGN KEY (mail_idmail) REFERENCESmail(idmail) ON DELETE NO ACTION ON UPDATE NO ACTION)

you are getting a constraint violation exception. I think it is on the foreign key from attachment to mail, as evidenced by
foreign key constraint fails (`maildb`.`attachment`, CONSTRAINT `fk_Attachment_mail1` FOREIGN KEY (`mail_idmail`)
I noticed you are not specifying a generator for your id. See this documentation
http://docs.jboss.org/hibernate/core/3.3/reference/en/html/mapping.html#mapping-declaration-id
since you did not specify the generator, the default is 'assigned' which means you have to programmatically assign the ids to the objects before you save them, which might or might not be what you want.
You didn't show us the code for how your Mail entity relates to the Attachment entity, or how you create your entities, which would all me to help more...depending on how you do it, hibernate might or might not be able to assign the foreign key in the attachment class.
EDIT -- from your comments, you are missing a few things. Try assigning the id of the mail entity to the attachment in your addAttachment method on mail. If you want the db to assign the id, you need to look up how to have the id column of the tables auto-increment for whatever RDBMS system you are using, and then you change add a generator to the id mappings of the entities. The generator will probably be 'identity' or 'increment' depending on the RDBMS.

As you want to make a bi-directionnal relation, you should indicate to your Attachment the Mail object and not only the Id :
In the Attcahment class, remove
private int mailId;
and replace it by
private Mail mail;
with the correct setter and getter.
In the Xml mapping file:
<property name="mailId">
<column name="mail_idmail"></column>
</property>
should be replaced by :
<many-to-one name="mail"
column="mail_idmail" not-null="true"/>
By the way, your hashCode/equals methods are crap.
You should read this : http://community.jboss.org/wiki/EqualsandHashCode
Anyway, it's better to not override them than have them wrong.

Related

EclipseLink FetchType.EAGER not always loaded eagerly

We are facing a strange problem occurring within our application using eclipselink. We built a multi-tenancy application which keeps several tenants within one table, separated by a tenancy row. The tenant and a separate entityid form the composite key for each entry. We configured the shared cache and everything works well for most of the time. However, sooner or later while using the application, we face situations where eager loading of related entities does not always work properly. The problem is shown in the following example:
The application loads macroallocations by the id of another entity:
#Entity
#Multitenant(value=MultitenantType.SINGLE_TABLE)
#TenantDiscriminatorColumn(name = DatabaseBindingIds.MACROALLOCATION_TENANT, contextProperty = MULTITENANT_PROPERTY_DEFAULT, primaryKey = true)
#Cache(type=CacheType.SOFT,size=100000)
public class MacroAllocation extends ReadWriteRecord {
/**
* The entity id of this macroallocation.
*/
#Id
#Column(name=DatabaseBindingIds.MACROALLOCATION_ID)
private String entityId;
/**
* The phase this macroallocation belongs to.
*/
#ManyToOne(fetch=FetchType.EAGER, optional=false)
//#BatchFetch(BatchFetchType.JOIN)
#JoinColumn(name=DatabaseBindingIds.MACROALLOCATION_PHASE_ID,referencedColumnName=DatabaseBindingIds.PHASE_ID, insertable=true, updatable=true)
private Phase phase;
/**
* The resource this macroallocation is assigned to.
*/
#ManyToOne(fetch=FetchType.EAGER, optional=false)
//#BatchFetch(BatchFetchType.JOIN)
#JoinColumn(name=DatabaseBindingIds.MACROALLOCATION_RESOURCE_ID, referencedColumnName=DatabaseBindingIds.RESOURCE_ID, insertable=true, updatable=true)
private Resource resource;
/**
* The duration of the allocation.
*/
#Column
#Convert(converter = DurationConverter.class)
private Duration duration;
/**
* Get the macroallocation id.
* #exception IllegalStateException EntityId can never be null.
*/
#Override
public String getId() {
if(entityId == null){
throw new IllegalStateException("[Constraint violation] entityId can not be null in " + this.getClass().getSimpleName());
}
return entityId;
}
/**
* Set the full id of this macroallocation.
* #exception IllegalStateException EntityId can never be null.
*/
#Override
public void setId(String entityId) {
markNew();
this.entityId = entityId;
if(entityId == null){
throw new IllegalStateException("[Constraint violation] entityId can not be null in " + this.getClass().getSimpleName());
}
}
/**
* Get the phase to which the macroallocation belongs.
* #exception IllegalStateException Phase can never be null.
*/
public Phase getPhase() {
if(phase == null){
throw new IllegalStateException("[Constraint violation] phase can not be null in " + this.getClass().getSimpleName());
}
return phase;
}
/**
* Set the phase to which the macroallocation belongs.
* #exception IllegalStateException Phase can never be null.
*/
public void setPhase(Phase x) {
phase = x;
if(phase == null){
throw new IllegalStateException("[Constraint violation] phase can not be null in " + this.getClass().getSimpleName());
}
}
/**
* Get the resource this macroallocation is assigned to.
* #exception IllegalStateException Resource can never be null.
*/
public Resource getResource() {
if(resource == null){
throw new IllegalStateException("[Constraint violation] resource can not be null in " + this.getClass().getSimpleName());
}
return resource;
}
/**
* Set the resource this macroallocation is assigned to.
* #exception IllegalStateException Resource can never be null.
*/
public void setResource(Resource x) {
resource = x;
if(resource == null){
throw new IllegalStateException("[Constraint violation] resource can not be null in " + this.getClass().getSimpleName());
}
}
/**
* Get the duration of this macroallocation.
* #return duration - can be null.
*/
public Duration getDuration() {
return duration;
}
/**
* Set the duration of this macroallocation.
* #param duration - can be null.
*/
public void setDuration(Duration x) {
duration = x;
}
}
To populate our application layer object based on the database layer entities, we usually get more information from related entities the following way:
macroAllocation.getPhase().getScenario().getProject().getId()
The phase should be eagerly loaded with the macroallocation and the scenario should be eagerly loaded as can be seen in the definition of the phase below:
#Entity
#Multitenant(value=MultitenantType.SINGLE_TABLE)
#TenantDiscriminatorColumn(name = DatabaseBindingIds.PHASE_TENANT, contextProperty = MULTITENANT_PROPERTY_DEFAULT, primaryKey = true)
#Cache(type=CacheType.SOFT,size=10000)
public class Phase extends ReadWriteRecord {
/**
* The entity id of this phase.
*/
#Id
#Column(name=DatabaseBindingIds.PHASE_ID)
private String entityId;
#OneToOne(fetch=FetchType.LAZY, cascade= CascadeType.PERSIST) // one to one mappings are directly mapped using the phase primary keys
#BatchFetch(BatchFetchType.JOIN)
#JoinColumn(name=DatabaseBindingIds.PHASE_ID, referencedColumnName=DatabaseBindingIds.PROPERTYSET_ID, insertable=false, updatable=false)
private PropertySet propertySet;
#OneToOne(fetch=FetchType.LAZY, cascade= CascadeType.PERSIST) // one to one mappings are directly mapped using the phase primary keys
#BatchFetch(BatchFetchType.JOIN)
#JoinColumn(name=DatabaseBindingIds.PHASE_ID, referencedColumnName=DatabaseBindingIds.LOGSET_ID, insertable=false, updatable=false)
private LogSet logSet;
#OneToOne(fetch=FetchType.LAZY, cascade= CascadeType.PERSIST) // one to one mappings are directly mapped using the phase primary keys
#BatchFetch(BatchFetchType.JOIN)
#JoinColumn(name=DatabaseBindingIds.PHASE_ID, referencedColumnName=DatabaseBindingIds.COSTSSET_ID, insertable=false, updatable=false)
private CostsSet costsSet;
#OneToOne(fetch=FetchType.LAZY, cascade= CascadeType.PERSIST) // one to one mappings are directly mapped using the phase primary keys
#BatchFetch(BatchFetchType.JOIN)
#JoinColumn(name=DatabaseBindingIds.PHASE_ID, referencedColumnName=DatabaseBindingIds.TODOSET_ID, insertable=false, updatable=false)
private TodoSet todoSet;
#ManyToOne(fetch=FetchType.EAGER, optional=false)
#JoinColumn(name=DatabaseBindingIds.PHASE_SCENARIO_ID, referencedColumnName=DatabaseBindingIds.SCENARIO_ID, insertable=true, updatable=true)
private Scenario scenario;
#ManyToOne(fetch=FetchType.EAGER)
#JoinColumn(name=DatabaseBindingIds.PHASE_PARENTPHASE_ID, referencedColumnName=DatabaseBindingIds.PHASE_ID, insertable=true, updatable=true)
private Phase parentPhase;
#Column
private Double sortIndex;
#Column
private String name;
#Column
private String description;
#Column
private String imageUrl;
#Column
#Convert(converter = DurationConverter.class)
private Duration budget;
#Column
#Convert(converter = DurationConverter.class)
private Duration planned;
#Column
#Convert(converter = PointInTimeConverter.class)
private PointInTime.Utc beg;
#Column//(name="\"End\"") // If you think you want to add this, check first why they are not escaped by the EclipseLink SessionCustomizer
#Convert(converter = PointInTimeConverter.class)
private PointInTime.Utc end;
#Column
private Boolean fixed;
#Column
private Integer progress;
#Column
private Boolean autoProgress;
#Column
private String costCenter;
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name=DatabaseBindingIds.PHASE_OWNER_ID, referencedColumnName=DatabaseBindingIds.RESOURCE_ID, insertable=true, updatable=true)
private Resource owner;
#Column
private String color;
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name=DatabaseBindingIds.PHASE_REQUIRED_SKILL_ID, referencedColumnName=DatabaseBindingIds.RESOURCE_ID, insertable=true, updatable=true)
private Resource requiredSkill;
#OneToMany(mappedBy="fromPhase", fetch=FetchType.LAZY)
private List<PhaseDependency> forwardDependencies;
#OneToMany(mappedBy="toPhase", fetch=FetchType.LAZY)
private List<PhaseDependency> reverseDependencies;
/**
* Get the phase id.
* #exception IllegalStateException EntityId can never be null.
*/
#Override
public String getId() {
if(entityId == null){
throw new IllegalStateException("[Constraint violation] entityId can not be null in " + this.getClass().getSimpleName());
}
return entityId;
}
/**
* Set the full id of this phase.
* #exception IllegalStateException EntityId can never be null.
*/
#Override
public void setId(String entityId) {
markNew();
this.entityId = entityId;
if(entityId == null){
throw new IllegalStateException("[Constraint violation] entityId can not be null in " + this.getClass().getSimpleName());
}
propertySet = new PropertySet();
propertySet.setId(entityId);
logSet = new LogSet();
logSet.setId(entityId);
costsSet = new CostsSet();
costsSet.setId(entityId);
todoSet = new TodoSet();
todoSet.setId(entityId);
}
/**
* Get the property set of the phase.
* #exception IllegalStateException propertySet can never be null.
*/
public PropertySet getPropertySet() {
if(propertySet == null){
throw new IllegalStateException("[Constraint violation] propertySet can not be null in " + this.getClass().getSimpleName());
}
return propertySet;
}
/**
* Get the log set of the phase.
* #exception IllegalStateException logSet can never be null.
*/
public LogSet getLogSet() {
if(logSet == null){
throw new IllegalStateException("[Constraint violation] logSet can not be null in " + this.getClass().getSimpleName());
}
return logSet;
}
/**
* Get the costs set of the phase.
* #exception IllegalStateException costsSet can never be null.
*/
public CostsSet getCostsSet() {
if(costsSet == null){
throw new IllegalStateException("[Constraint violation] costsSet can not be null in " + this.getClass().getSimpleName());
}
return costsSet;
}
/**
* Get the todo set of the phase.
* #exception IllegalStateException todoSet can never be null.
*/
public TodoSet getTodoSet() {
if(todoSet == null){
throw new IllegalStateException("[Constraint violation] todoSet can not be null in " + this.getClass().getSimpleName());
}
return todoSet;
}
/**
* Get the scenario of the phase.
* #exception IllegalStateException scenario can never be null.
*/
public Scenario getScenario() {
if(scenario == null){
throw new IllegalStateException("[Constraint violation] scenario can not be null in " + this.getClass().getSimpleName());
}
return scenario;
}
/**
* Set the scenario of the phase.
* #exception IllegalStateException scenario can never be null.
*/
public void setScenario(Scenario x) {
scenario = x;
if(scenario == null){
throw new IllegalStateException("[Constraint violation] scenario can not be null in " + this.getClass().getSimpleName());
}
}
/**
* Get the parent phase of this phase.
* #return parentPhase - can be null.
*/
public Phase getParentPhase() {
return parentPhase;
}
/**
* Set the parent phase of this phase.
* #return parentPhase - can be null.
*/
public void setParentPhase(Phase x) {
parentPhase = x;
}
/**
* Get the sort index of the phase.
* #return
*/
public double getSortIndex() {
return sortIndex == null ? 0.0 : sortIndex;
}
/**
* Set the sort index of the phase.
* #param x
*/
public void setSortIndex(double x) {
sortIndex = x;
}
/**
* Get the name of the phase.
* #return name - can be null.
*/
public String getName() {
return name;
}
/**
* Set the name of this phase.
* #param name - can be null.
*/
public void setName(String x) {
name = x;
}
/**
* Get the description of the phase.
* #return description - can be null.
*/
public String getDescription() {
return description;
}
/**
* Set the description of this phase.
* #param description - can be null.
*/
public void setDescription(String x) {
description = x;
}
/**
* Get the image url of the phase.
* #return imageUrl - can be null.
*/
public String getImageUrl() {
return imageUrl;
}
/**
* Set the imag url of this phase.
* #param imageUrl - can be null.
*/
public void setImageUrl(String x) {
imageUrl = x;
}
/**
* Get the budget of the phase.
* #return budget - can be null.
*/
public Duration getBudget() {
return budget;
}
/**
* Set the budget of this phase.
* #param budget - can be null.
*/
public void setBudget(Duration x) {
budget = x;
}
/**
* Get the planned duration of the phase.
* #return planned - can be null.
*/
public Duration getPlanned() {
return planned;
}
/**
* Set the planned duration of this phase.
* #param planned - can be null.
*/
public void setPlanned(Duration x) {
planned = x;
}
/**
* Get the beginning of the phase.
* #return beg - can be null.
*/
public PointInTime.Utc getBeg() {
return beg;
}
/**
* Set the beginning of this phase.
* #param beg - can be null.
*/
public void setBeg(PointInTime.Utc x) {
beg = x;
}
/**
* Get the ending of the phase.
* #return end - can be null.
*/
public PointInTime.Utc getEnd() {
return end;
}
/**
* Set the ending of this phase.
* #param end - can be null.
*/
public void setEnd(PointInTime.Utc x) {
end = x;
}
/**
* Get if the phase is fixed.
* #return
*/
public boolean getFixed() {
return fixed == null ? false : fixed;
}
/**
* Set if the phase is fixed.
* #param x
*/
public void setFixed(boolean x) {
fixed = x;
}
/**
* Get the progress of the phase.
* #return
*/
public int getProgress() {
return progress == null ? 0 : progress;
}
/**
* Set the progress of this phase.
* #param
*/
public void setProgress(int x) {
progress = x;
}
/**
* Get if the phase progresses automatically.
* #exception IllegalStateException autoProgress can never be null.
*/
public boolean getAutoProgress() {
return autoProgress == null ? false : autoProgress;
}
/**
* Get if the phase progresses automatically.
* #exception IllegalStateException autoProgress can never be null.
*/
public void setAutoProgress(boolean x) {
autoProgress = x;
}
... not relevant getters and setters...
}
To get proper exceptions when our problem occurs, we added IllegalStateExceptions being thrown that tell us similarly to the db constraints, that an eager loading constraint has been violated. When the problem occurs, we get:
java.lang.IllegalStateException: [Constraint violation] scenario can not be null in Phase
This means that during the loading of the macroallocation, the scenario was not loaded.
The only workaround we found is by accessing the scenario while the database session is still open, but from our understanding, this should only be necessary to load lazy loaded entity relations. What could the problem be? Below are the macroallocation loading method:
#Override
public List<MacroAllocation> loadMacroAllocationsByResource(String resourceId) throws DataAccessException {
try(DatabaseSession session = new DatabaseSession(tenant)) {
List<MacroAllocation> macroAllocations = session.loadByQuery(MacroAllocation.class,
"SELECT ma FROM MacroAllocation AS ma "
+ "WHERE ma.resource.entityId = ?1 " // with matching primary key in resource
+ "AND ma.deleted = 0", // and not deleted
resourceId);
//Workaround: Some objects are not eagerly fetched in some cases. Here we do that explicitly.
macroAllocations.stream().forEach((m) -> {
session.fetch(m.getPhase().getScenario());
session.fetch(m.getPhase().getScenario().getProject());
});
return macroAllocations;
} catch(RuntimeException e) {
throw new DataAccessException(e);
}
}
and the database session we use within this method:
public final class DatabaseSession implements AutoCloseable {
/**
* Maximum latency in milliseconds for a JPA operation, after which a warning shall be logged.
*/
private static final double MAX_LATENCY = 100.0;
/**
* Maximum duration in milliseconds for a session, after which a warning shall be logged.
*/
private static final double MAX_LATENCY_TOT = 1000.0;
/**
* Our logger, never null.
*/
private static final Logger log = LoggerFactory.getLogger(DatabaseSession.class);
/**
* The factory for creating EntityManager instances, created in initEntityManagerFactory() or in the constructor.
*/
private static String persistenceUnitName;
/**
* The EntityManager instance to access the database, created from the factory in the constructor.
*/
private EntityManager em;
/**
* The time when the instance was created, useful for measure total time of the session.
*/
private final long ttot = System.nanoTime();
/**
* Indicates whether commit() as been called.
*/
private boolean committed;
private String tenant;
private static final Cache<String, EntityManagerFactory> emfs = new Cache<>(tenant -> { // create if absent
synchronized (DatabaseSession.class) {
HashMap<String,String> properties = new HashMap<>();
properties.put(SESSION_NAME, (tenant!=null && tenant != "")?tenant+"-session":"non-tenant-session");
properties.put(MULTITENANT_PROPERTY_DEFAULT, tenant);
if(persistenceUnitName == null){
log.debug("Persistence Unit Name defaults to: default");
persistenceUnitName = "default";
}
return Persistence.createEntityManagerFactory(persistenceUnitName, properties);
}
},
(entityManagerFactory) -> { // on remove
entityManagerFactory.close();
});
/**
* Opens a new non-tenant specific session and begins a new transaction.
*
* Only shared, non-tenant specific entities can be retrieved. Multitenancy entities can not be retrieved using this session. To retrieve tenant specific entities, create a tenant session using <b>new DataSession(tenant)</b>
*/
public DatabaseSession() {
this.tenant = "";
synchronized (DatabaseSession.class) {
emfs.get(tenant);
}
createEntityManager();
}
/**
* Opens a new tenant session and begins a new transaction.
*
* Multitenancy entities can be retrieved using this session.
*/
public DatabaseSession(String tenant) {
if(tenant == null || tenant.equals("")){
log.error("Trying to create a non-tenant database session with tenant specific constructor? Use constructor DatabaseSession() instead.");
tenant = "";
}
this.tenant = tenant;
synchronized (DatabaseSession.class) {
emfs.get(tenant); // creates a new factory in a synchronized manner.
}
createEntityManager();
}
/**
* #note: Should only be called publicly by unit tests.
*/
public void createEntityManager() {
em = emfs.get(tenant).createEntityManager();
em.getTransaction().begin();
}
/**
* Initializes the EntityManagerFactory (optional, useful for testing).
* <p>
* If this method is not called, the EntityManagerFactory is initialized automatically with persistence unit "default" when the first instance is created.
* <p>
* Persistence units are defined in conf/META-INF/persistence.xml.
*
* #param persistenceUnitName
* the name of the persistence unit to be used, must match the XML attribute /persistence/persistence-unit/#name.
*/
public static void initEntityManagerFactory(String pun) {
persistenceUnitName = pun;
}
/**
* Sets up all factories to prevent eclipselink from drop and creating the db.
*
* #note: Should only be called by unit tests.
*/
public void setupEntityManagerFactories(List<String> tenants) {
log.warn("SetupEntityManagerFactories should only be called by Unit tests.");
for(String tenant: tenants){
emfs.get(tenant);
}
}
/**
* Closes the connection to the database completely. For Unit tests, this drops and recreates the database to advance to the next unit test with a fresh one.
*
* #note: Should only be called by unit tests.
*/
public void shutdownDB() {
log.warn("ShutdownDB should only be called by Unit tests.");
em.close();
em = null;
DatabaseSession.emfs.clear(); // closes entity manager factory on close
}
#Override
public void close() {
try {
if (!committed) {
if (em != null) {
em.getTransaction().rollback();
}
}
} finally {
if (committed) {
if (em != null) {
em.close();
}
}
double latency = (System.nanoTime() - ttot) / 1000000.0;
if (latency > MAX_LATENCY_TOT) {
log.warn("Duration of session was " + latency + "ms.");
} else {
log.debug("Duration of session was " + latency + "ms.");
}
}
}
/**
* Commits the transaction, must explicitly be done before the session is closed.
*/
public void commit() {
long t = System.nanoTime();
em.flush();
em.getTransaction().commit();
committed = true;
double latency = (System.nanoTime() - t) / 1000000.0;
if (latency > MAX_LATENCY) {
warn("Latency of commit() was %sms.", latency);
}
}
public <T extends PersistentRecord> List<T> loadAll(Class<T> clazz) {
return loadAll(clazz, true);
}
public <T extends PersistentRecord> List<T> loadAll(Class<T> clazz, boolean filterDeleted) {
log("loadAll(%s)", clazz.getSimpleName());
long t = System.nanoTime();
CriteriaBuilder b = em.getCriteriaBuilder();
CriteriaQuery<T> q = b.createQuery(clazz);
Metamodel m = em.getMetamodel();
EntityType<T> et = m.entity(clazz);
Root<T> r = q.from(clazz);
q.select(r);
if (filterDeleted) {
q.where(b.equal(r.get(et.getAttribute("deleted").getName()), 0));
}
List<T> results = em.createQuery(q).getResultList();
double latency = (System.nanoTime() - t) / 1000000.0;
if (latency > MAX_LATENCY) {
warn("Latency of loadAll(%s) was %sms.", clazz.getSimpleName(), latency);
}
return results;
}
public <T extends PersistentRecord> int count(Class<T> clazz) {
return count(clazz, true);
}
public <T extends PersistentRecord> int count(Class<T> clazz, boolean filterDeleted) {
log("count(%s)", clazz.getSimpleName());
long t = System.nanoTime();
CriteriaBuilder b = em.getCriteriaBuilder();
CriteriaQuery<T> q = b.createQuery(clazz);
Metamodel m = em.getMetamodel();
EntityType<T> et = m.entity(clazz);
Root<T> r = q.from(clazz);
q.select(r);
if (filterDeleted) {
q.where(b.equal(r.get(et.getAttribute("deleted").getName()), 0));
}
List<T> result = em.createQuery(q).getResultList();
double latency = (System.nanoTime() - t) / 1000000.0;
if (latency > MAX_LATENCY) {
warn("Latency of count(%s) was %sms.", clazz.getSimpleName(), latency);
}
return result.size();
}
public <T extends PersistentRecord> T load(Class<T> clazz, String id) {
return load(clazz, id, true);
}
public <T extends PersistentRecord> T load(Class<T> clazz, String id, boolean filterDeleted) {
log("load(%s, %s)", clazz.getSimpleName(), id);
long t = System.nanoTime();
T result = em.find(clazz, id);
if (filterDeleted) {
result = filterDeleted(result);
}
double latency = (System.nanoTime() - t) / 1000000.0;
if (latency > MAX_LATENCY) {
warn("Latency of load(%s, %s) was %sms.", clazz.getSimpleName(), id, latency);
}
return result;
}
public <T extends PersistentRecord> List<T> loadByQuery(Class<T> clazz, String query, Object... params) {
log("loadByQuery(%s, '%s', %s)", clazz.getSimpleName(), query, format(params));
long t = System.nanoTime();
TypedQuery<T> q = em.createQuery(query, clazz);
for (int i = 0; i < params.length; i++) {
q.setParameter(i + 1, params[i]);
}
List<T> result = q.getResultList();
result = filterDeleted(result);
double latency = (System.nanoTime() - t) / 1000000.0;
if (latency > MAX_LATENCY) {
warn("Latency of loadByQuery(%s, '%s', %s) was %sms.", clazz.getSimpleName(), query, format(params), latency);
}
return result;
}
public <T extends PersistentRecord> T loadSingleByQuery(Class<T> clazz, String query, Object... params) {
log("loadSingleByQuery(%s, '%s', %s)", clazz.getSimpleName(), query, format(params));
long t = System.nanoTime();
TypedQuery<T> q = em.createQuery(query, clazz);
for (int i = 0; i < params.length; i++) {
q.setParameter(i + 1, params[i]);
}
List<T> result = q.getResultList();
result = filterDeleted(result);
double latency = (System.nanoTime() - t) / 1000000.0;
if (latency > MAX_LATENCY) {
warn("Latency of loadSingleByQuery(%s, '%s', %s) was %sms.", clazz.getSimpleName(), query, format(params), latency);
}
return result.size() > 0 ? result.get(0) : null;
}
... storing methods not relevant here...
}

JAX-WS passing bean methods to clients

I have made a web service in Netbeans. I am trying to understand why the methods of the bean does not get generated by the client.
Here is the bean.
package OnlineAuction;
import java.io.Serializable;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.Date;
public class Auction implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private Product product;
private Timestamp added;
private Timestamp expire;
private BigDecimal startingBid;
private BigDecimal reserve;
/**
*
* #return
*/
public Long getId() {
return id;
}
/**
*
* #param id
*/
public void setId(Long id) {
this.id = id;
}
#Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Auction)) {
return false;
}
Auction other = (Auction) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}
#Override
public String toString() {
return "OnlineAuction.Auction[ id=" + id + " ]";
}
/**
*
* #return
*/
public Product getProduct() {
return product;
}
/**
*
* #param product
*/
public void setProduct(Product product) {
this.product = product;
}
/**
*
* #return
*/
public Timestamp getAdded() {
return added;
}
/**
*
* #param added
*/
public void setAdded(Timestamp added) {
this.added = added;
}
/**
*
*/
public void setAddedNow() {
this.added = getTimestampNow();
}
private Timestamp getTimestampNow() {
java.util.Date date = new java.util.Date();
return new Timestamp(date.getTime());
}
/**
*
* #return
*/
public Timestamp getExpire() {
return expire;
}
/**
*
* #param expire
*/
public void setExpire(Timestamp expire) {
this.expire = expire;
}
/**
* Sets the expiry time of the auction by adding the hours to the added date.
* If the added date is not set this function will set the added date to current time.
* #param hours to be added to the added time of the auction
*/
public void setExpire(int hours) {
// Set added time if null
if (this.added == null) {
this.setAddedNow();
}
Calendar cal = Calendar.getInstance();
cal.setTime(this.added);
cal.add(Calendar.HOUR, hours);
Date date = cal.getTime();
this.expire = new Timestamp(date.getTime());
}
/**
*
* #return
*/
public BigDecimal getStartingBid() {
return startingBid;
}
/**
*
* #param startingBid
*/
public void setStartingBid(BigDecimal startingBid) {
this.startingBid = startingBid;
}
/**
*
* #return
*/
public BigDecimal getReserve() {
return reserve;
}
/**
*
* #param reserve
*/
public void setReserve(BigDecimal reserve) {
this.reserve = reserve;
}
public boolean isAuctionExpired() {
boolean expired;
if (this.getTimestampNow().compareTo(this.expire) > 0) {
// now is greater than expire date
expired = true;
} else {
// now is less than expire date
expired = false;
}
return expired;
}
}
And here is the generated source by JAX-WS for the client.
package OnlineAuction.client;
import java.math.BigDecimal;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlType;
/**
* <p>Java class for auction complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* <complexType name="auction">
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <sequence>
* <element name="added" type="{http://OnlineAuction/}timestamp" minOccurs="0"/>
* <element name="expire" type="{http://OnlineAuction/}timestamp" minOccurs="0"/>
* <element name="id" type="{http://www.w3.org/2001/XMLSchema}long" minOccurs="0"/>
* <element name="product" type="{http://OnlineAuction/}product" minOccurs="0"/>
* <element name="reserve" type="{http://www.w3.org/2001/XMLSchema}decimal" minOccurs="0"/>
* <element name="startingBid" type="{http://www.w3.org/2001/XMLSchema}decimal" minOccurs="0"/>
* </sequence>
* </restriction>
* </complexContent>
* </complexType>
* </pre>
*
*
*/
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "auction", propOrder = {
"added",
"expire",
"id",
"product",
"reserve",
"startingBid"
})
public class Auction {
protected Timestamp added;
protected Timestamp expire;
protected Long id;
protected Product product;
protected BigDecimal reserve;
protected BigDecimal startingBid;
/**
* Gets the value of the added property.
*
* #return
* possible object is
* {#link Timestamp }
*
*/
public Timestamp getAdded() {
return added;
}
/**
* Sets the value of the added property.
*
* #param value
* allowed object is
* {#link Timestamp }
*
*/
public void setAdded(Timestamp value) {
this.added = value;
}
/**
* Gets the value of the expire property.
*
* #return
* possible object is
* {#link Timestamp }
*
*/
public Timestamp getExpire() {
return expire;
}
/**
* Sets the value of the expire property.
*
* #param value
* allowed object is
* {#link Timestamp }
*
*/
public void setExpire(Timestamp value) {
this.expire = value;
}
/**
* Gets the value of the id property.
*
* #return
* possible object is
* {#link Long }
*
*/
public Long getId() {
return id;
}
/**
* Sets the value of the id property.
*
* #param value
* allowed object is
* {#link Long }
*
*/
public void setId(Long value) {
this.id = value;
}
/**
* Gets the value of the product property.
*
* #return
* possible object is
* {#link Product }
*
*/
public Product getProduct() {
return product;
}
/**
* Sets the value of the product property.
*
* #param value
* allowed object is
* {#link Product }
*
*/
public void setProduct(Product value) {
this.product = value;
}
/**
* Gets the value of the reserve property.
*
* #return
* possible object is
* {#link BigDecimal }
*
*/
public BigDecimal getReserve() {
return reserve;
}
/**
* Sets the value of the reserve property.
*
* #param value
* allowed object is
* {#link BigDecimal }
*
*/
public void setReserve(BigDecimal value) {
this.reserve = value;
}
/**
* Gets the value of the startingBid property.
*
* #return
* possible object is
* {#link BigDecimal }
*
*/
public BigDecimal getStartingBid() {
return startingBid;
}
/**
* Sets the value of the startingBid property.
*
* #param value
* allowed object is
* {#link BigDecimal }
*
*/
public void setStartingBid(BigDecimal value) {
this.startingBid = value;
}
}
So why is my bean method isAuctionExpired() not in the generated source? I am able to cheat this by adding a auctionExpired property, but this is not how I want to do this.
The JAX-WS client is generated using the WSDL of the webservice. The WSDL only has the properties of the types that will be used for communication between the server and the client. So, you will never be able to pass the method implementation across server and client. The information in the below annotation is all the client class generator has while generating the client;
#XmlType(name = "auction", propOrder = {
"added",
"expire",
"id",
"product",
"reserve",
"startingBid"
})
This information is taken from the WSDL.
You have to understand that XML is used for communication between the server and the client. So, code from the webservice cannot be passed to the client or vice versa. The webservice and the client can be written in two different technologies. So, passing java code to the client does not make any sense if the client is implemented in any other language.
In short, you can pass information between the client and server but not behaviour.

Java Hibernate - IllegalArgumentException

I have these 2 classes - Letadlo and Letiste (Plane and (Home)Airport). While saving data to DB, using java and hibernate , I'm getting this exception:
16285 [Thread-2] ERROR org.hibernate.property.BasicPropertyAccessor - IllegalArgumentException in class: mapy.Letiste, getter method of property: id
org.hibernate.PropertyAccessException: IllegalArgumentException occurred calling getter of mapy.Letiste.id
at org.hibernate.property.BasicPropertyAccessor$BasicGetter.get(BasicPropertyAccessor.java:198)
at org.hibernate.tuple.entity.AbstractEntityTuplizer.getIdentifier(AbstractEntityTuplizer.java:227)
at org.hibernate.persister.entity.AbstractEntityPersister.getIdentifier(AbstractEntityPersister.java:3876)
at org.hibernate.persister.entity.AbstractEntityPersister.isTransient(AbstractEntityPersister.java:3584)
at org.hibernate.engine.ForeignKeys.isTransient(ForeignKeys.java:203)
at org.hibernate.engine.ForeignKeys$Nullifier.isNullifiable(ForeignKeys.java:159)
at org.hibernate.engine.ForeignKeys$Nullifier.nullifyTransientReferences(ForeignKeys.java:91)
at org.hibernate.engine.ForeignKeys$Nullifier.nullifyTransientReferences(ForeignKeys.java:69)
at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:310)
at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:203)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:129)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:210)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:195)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:117)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:685)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:677)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:673)
at logika.UkladaniDoDtb.run(UkladaniDoDtb.java:34)
at java.lang.Thread.run(Thread.java:744)
Caused by: java.lang.IllegalArgumentException: object is not an instance of declaring class
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.hibernate.property.BasicPropertyAccessor$BasicGetter.get(BasicPropertyAccessor.java:172)
... 19 more
Saving part:
HibernateFactory.buildSessionFactory();
Session session = HibernateFactory.openSession();
session.beginTransaction().begin();
for(Object o: DocasneUloziste.objektyKeSmazani){
session.delete(o);
}
for (Linka l : DocasneUloziste.linky) {
session.saveOrUpdate(l);
}
for (Letadlo l : DocasneUloziste.letadla) { //this is 34 line
session.saveOrUpdate(l);
}
for (Letiste d : DocasneUloziste.seznamLetist) {
session.saveOrUpdate(d);
}
session.getTransaction().commit();
session.close();
xml of Letadlo:
<class name="mapy.Letiste">
<meta attribute="class-description">Tato trida obsahuje info o domovskem letisti</meta>
<id name="id" type="long" column="LETISTE_ID">
<generator class="native" />
</id>
<property name="kodLetiste" type="string" not-null="true" length="3" column="KOD_LETISTE"/>
<property name="mesto" type="string" not-null="true" length="35" column="MESTO" />
<set name="obsluhaLetadel" cascade="all">
<key column="LETISTE_ID" />
<one-to-many class="mapy.Letadlo" />
</set>
</class>
xml of Letiste:
<class name="mapy.Letiste">
<meta attribute="class-description">Tato trida obsahuje info o domovskem letisti</meta>
<id name="id" type="long" column="LETISTE_ID">
<generator class="native" />
</id>
<property name="kodLetiste" type="string" not-null="true" length="3" column="KOD_LETISTE"/>
<property name="mesto" type="string" not-null="true" length="35" column="MESTO" />
<set name="obsluhaLetadel" cascade="all">
<key column="LETISTE_ID" />
<one-to-many class="mapy.Letadlo" />
</set>
</class>
Class of letadlo contains all variables with getter and setters I had in XML and constructor with no parameter.
Thanks for any suggestion!
EDIT: Letiste Class
public class Letiste {
private Long id;
private String kodLetiste;
private String mesto;
private Set<Letadlo> obsluhaLetadel = new HashSet<Letadlo>();
public Letiste() {
}
public Letiste(String kodLetiste, String mesto) {
this.kodLetiste = kodLetiste;
this.mesto = mesto;
}
public String getKodLetiste() {
return kodLetiste;
}
public void setKodLetiste(String kodLetiste) {
this.kodLetiste = kodLetiste;
}
public String getMesto() {
return mesto;
}
public void setMesto(String mesto) {
this.mesto = mesto;
}
#Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Letiste other = (Letiste) obj;
if ((this.kodLetiste == null) ? (other.kodLetiste != null) : !this.kodLetiste.equals(other.kodLetiste)) {
return false;
}
if ((this.mesto == null) ? (other.mesto != null) : !this.mesto.equals(other.mesto)) {
return false;
}
return true;
}
#Override
public int hashCode() {
int hash = 7;
hash = 13 * hash + (this.kodLetiste != null ? this.kodLetiste.hashCode() : 0);
hash = 13 * hash + (this.mesto != null ? this.mesto.hashCode() : 0);
return hash;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Set<Letadlo> getObsluhaLetadel() {
return obsluhaLetadel;
}
public void setObsluhaLetadel(Set<Letadlo> obsluhaLetadel) {
this.obsluhaLetadel = obsluhaLetadel;
}
EDIT: Letadlo Class
public class Letadlo {
private Long id;
private String kodLetadla;
private String kapacita;
private Integer dolet;
private Set<Linka> seznamLinek = new HashSet<Linka>();
private String letiste;
public Letadlo() {
}
public Letadlo(String kodLetadla, String kapacita , Integer dolet, String letiste) {
this.kodLetadla = kodLetadla;
this.kapacita = kapacita;
this.dolet = dolet;
this.letiste = letiste;
}
/**
* #return the kodLetadla
*/
public String getKodLetadla() {
return kodLetadla;
}
/**
* #param kodLetadla the kodLetadla to set
*/
public void setKodLetadla(String kodLetadla) {
this.kodLetadla = kodLetadla;
}
/**
* #return the kapacita
*/
public String getKapacita() {
return kapacita;
}
/**
* #param kapacita the kapacita to set
*/
public void setKapacita(String kapacita) {
this.kapacita = kapacita;
}
/**
* #return the dolet
*/
public Integer getDolet() {
return dolet;
}
/**
* #param dolet the dolet to set
*/
public void setDolet(Integer dolet) {
this.dolet = dolet;
}
#Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Letadlo other = (Letadlo) obj;
if (this.kodLetadla != other.kodLetadla && (this.kodLetadla == null || !this.kodLetadla.equals(other.kodLetadla))) {
return false;
}
return true;
}
#Override
public int hashCode() {
int hash = 7;
hash = 79 * hash + (this.kodLetadla != null ? this.kodLetadla.hashCode() : 0);
hash = 79 * hash + (this.kapacita != null ? this.kapacita.hashCode() : 0);
hash = 79 * hash + (this.dolet != null ? this.dolet.hashCode() : 0);
return hash;
}
/**
* #return the id
*/
public Long getId() {
return id;
}
/**
* #param id the id to set
*/
public void setId(Long id) {
this.id = id;
}
/**
* #return the seznamLinek
*/
public Set<Linka> getSeznamLinek() {
return seznamLinek;
}
/**
* #param seznamLinek the seznamLinek to set
*/
public void setSeznamLinek(Set<Linka> seznamLinek) {
this.seznamLinek = seznamLinek;
}
/**
* #return the letiste
*/
public String getLetiste() {
return letiste;
}
/**
* #param letiste the letiste to set
*/
public void setLetiste(String letiste) {
this.letiste = letiste;
}

Hibernate with JPA won't create table

I want to create a table by using Hibernate + JPA. The problem is that whenever I run my code it won't create any tables. I have created already an empty database. I use Hibernate + JPA + HSQL + Maven.
Here is my persistence.xml:
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<!-- Provider of Persistence -->
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<!-- Classes, in which JPA-Annotations are read -->
<class>com.mysite.warehousebase.base.ProductData</class>
<properties>
<property name="hibernate.connection.driver_class" value="org.hsqldb.jdbcDriver"/>
<property name="hibernate.connection.url" value="jdbc:hsqldb:Warehouse"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
<property name="hibernate.connection.username" value="sa" />
<property name="hibernate.connection.password" value="" />
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
</properties>
</persistence-unit>
</persistence>
Here is my productData.java code:
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.hibernate.annotations.ForeignKey;
import org.hibernate.validator.NotNull;
#Entity
#Table(name = "products")
public class ProductData extends Entityclass {
private static final long serialVersionUID = 1L;
/*
//Product Addition Time
#NotNull
#Column(name = "added", nullable = false)
private Date productAdded;*/
//Product Name
#NotNull
#Column(name = "productname", nullable = false)
private String productName;
//Product Description
#Column(name = "productdescription", nullable = true)
private String productDescription;
//Product Size
#Column(name = "productsize", nullable = true)
private String productSize;
//Product Amount
#NotNull
#Column(name = "productamount", nullable = false)
private int productAmount;
//Product Left
//Attribute to be calculated in own method
#NotNull
#Column(name = "productleft", nullable = false)
private int productLeft;
//Product buy price
#NotNull
#Column(name = "productprice", nullable = false)
private double productPrice;
//Total cost
//Attribute to be calculated in own method
#NotNull
#Column(name = "totalproductprice", nullable = false)
private double totalProductPrice;
//Product sell price
#NotNull
#Column(name = "productsellprice", nullable = false)
private double productSellPrice;
//Product sale
//Attribute to be calculated in own method
#NotNull
#Column(name = "totalsellprice", nullable = false)
private double totalSellPrice;
//Difference between cost and sale (total)
//Attribute to be calculated in own method
#NotNull
#Column(name = "buyselldifference", nullable = false)
private double buySellDifference;
//Product status; ordered, at warehouse, reserved.
//Attribute to be calculated in own method
#NotNull
#Column(name = "productstatus", nullable = false)
private String productStatus;
#Column(name = "reservedproducts", nullable = true)
private int reservedProducts;
/**
* All Setters and Getters
*
*/
/**
* #return the productName
*/
public String getProductName() {
return productName;
}
/**
* #param productName the productName to set
*/
public void setProductName(String productName) {
this.productName = productName;
}
/**
* #return the productDescription
*/
public String getProductDescription() {
return productDescription;
}
/**
* #param productDescription the productDescription to set
*/
public void setProductDescription(String productDescription) {
this.productDescription = productDescription;
}
/**
* #return the productSize
*/
public String getProductSize() {
return productSize;
}
/**
* #param productSize the productSize to set
*/
public void setProductSize(String productSize) {
this.productSize = productSize;
}
/**
* #return the productAmount
*/
public int getProductAmount() {
return productAmount;
}
/**
* #param productAmount the productAmount to set
*/
public void setProductAmount(int productAmount) {
this.productAmount = productAmount;
}
/**
* #return the productLeft
*/
public int getProductLeft() {
return productLeft;
}
/**
* #param productLeft the productLeft to set
*/
public void setProductLeft(int productLeft) {
this.productLeft = productLeft;
}
/**
* #return the productPrice
*/
public double getProductPrice() {
return productPrice;
}
/**
* #param productPrice the productPrice to set
*/
public void setProductPrice(double productPrice) {
this.productPrice = productPrice;
}
/**
* #return the totalProductPrice
*/
public double getTotalProductPrice() {
return totalProductPrice;
}
/**
* #param totalProductPrice the totalProductPrice to set
*/
public void setTotalProductPrice(double totalProductPrice) {
this.totalProductPrice = totalProductPrice;
}
/**
* #return the productSellPrice
*/
public double getProductSellPrice() {
return productSellPrice;
}
/**
* #param productSellPrice the productSellPrice to set
*/
public void setProductSellPrice(double productSellPrice) {
this.productSellPrice = productSellPrice;
}
/**
* #return the totalSellPrice
*/
public double getTotalSellPrice() {
return totalSellPrice;
}
/**
* #param totalSellPrice the totalSellPrice to set
*/
public void setTotalSellPrice(double totalSellPrice) {
this.totalSellPrice = totalSellPrice;
}
/**
* #return the buySellDifference
*/
public double getBuySellDifference() {
return buySellDifference;
}
/**
* #param buySellDifference the buySellDifference to set
*/
public void setBuySellDifference(double buySellDifference) {
this.buySellDifference = buySellDifference;
}
/**
* #return the productStatus
*/
public String getProductStatus() {
return productStatus;
}
/**
* #param productStatus the productStatus to set
*/
public void setProductStatus(String productStatus) {
this.productStatus = productStatus;
}
/**
* #return the reservedProducts
*/
public int getReservedProducts() {
return reservedProducts;
}
/**
* #param reservedProducts the reservedProducts to set
*/
public void setReservedProducts(int reservedProducts) {
this.reservedProducts = reservedProducts;
}
/**
* #return the productSection
*/
public ProductSection getProductSection() {
return productSection;
}
/**
* #param productSection the productSection to set
*/
public void setProductSection(ProductSection productSection) {
this.productSection = productSection;
}
public ProductData(){
}
public ProductData(String productName){
this.productName = productName;
}
}
And my main.java code:
public static void main(String[] args) {
DataStructureTest testProduct = new DataStructureTest();
testProduct.testProductData();
}
What is wrong? Why Hibernate won't create a table that is needed? I have tried using hibernate.hbm2ddl.auto with value of "update". It won't help.
Can you try with
<property name="hibernate.hbm2ddl.auto" value="create"/>
Also 'transaction-type="RESOURCE_LOCAL" is defined in the persistence xml
I found the solution for this. For some reason value of
property name="hibernate.connection.url" value="jdbc:hsqldb:Warehouse"
won't work. So instead of what I did was that I created a database connection which value was following
jdbc:hsqldb:file:[folder name]
This folder name is user defined. So the new code of that particular line would be:
property name="hibernate.connection.url" value="jdbc:hsqldb:file:[folder name]"
Now everything is running smoothly and tables are created and updated :).

Hibernate insert error: ids for this class must be manually assigned before calling save():

I have this problem that i can't solve, this is my entity class:
/**
* #hibernate.class
* table="users.network_topic"
* #hibernate.cache usage="read-write"
*/
public class NetworkTopic implements Serializable, Idable{
/** identifier field */
private Long id;
/** persistent field */
private Long networkId;
/** persistent field */
private Long topicId;
private UserTopic topic;
private Network network;
/**
* #hibernate.id
* generator-class="assigned"
* type="java.lang.Long"
* column="id"
*/
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
/**
* #hibernate.property
* type="java.lang.Long"
* column="network_id"
* not-null="true"
*/
public Long getNetworkId() {
return networkId;
}
public void setNetworkId(Long networkId) {
this.networkId = networkId;
}
/**
* #hibernate.property
* type="java.lang.Long"
* column="user_topic_id"
* not-null="true"
*/
public Long getTopicId() {
return topicId;
}
public void setTopicId(Long topicId) {
this.topicId = topicId;
}
/**
* #hibernate.set
* lazy="true"
* inverse="true"
* cascade="none"
* #hibernate.key
* column="user_topic_id"
* #hibernate.one-to-many
* class="com.netblue.matchpoint.domain.UserTopic"
*
*/
public UserTopic getTopic() {
return topic;
}
public void setTopic(UserTopic topic) {
this.topic = topic;
}
/**
* #hibernate.set
* lazy="true"
* inverse="true"
* cascade="none"
* #hibernate.key
* column="network_id"
* #hibernate.one-to-many
* class="com.netblue.matchpoint.domain.Network"
*
*/
public Network getNetwork() {
return network;
}
public void setNetwork(Network network) {
this.network = network;
}
#Override
public String toString() {
return "Network[id=" + id + "]";
}
}
Then i try to save a new register with this code:
UserTopic topic = new UserTopic();
topic.setId(topicId);
topic.setName(ParseUtil.getString(map.get(MPConstants.TOPIC_NAME_PARAM)));
topic.setCreatedBy(ParseUtil.getInt(map.get(MPConstants.USER_ID)));
Date now = new Date();
topic.setCreatedDt(now);
topic.setLastUpdatedDt(now);
topic.setStatusId(Status.ACTIVE);
topic.setActivityCnt(0);
userTopicDao.saveOrUpdate(topic);
UserTopicMap utm = new UserTopicMap();
utm.setId(topicId);
utm.setMtid(topicId);
utm.setOtid(topicId);
utm.setIsDeleted(false);
utm.setLastUpdatedDt(now);
userTopicMapDao.saveOrUpdate(utm);
Network network = MpAuctionUtil.getNetworkById(networkId);
NetworkTopic networkTopic = new NetworkTopic();
networkTopic.setNetworkId(networkId);
networkTopic.setTopicId(topicId);
networkTopic.setNetwork(network);
networkTopic.setTopic(topic);
LOG.debug("userTopicService addObjSubscriber x networkId="+networkId+", topicId="+topicId);
networkTopicDao.saveOrUpdate(networkTopic);
The last lines are the ones that fail, if i remove them it works, i mean it saves topics ok, but when i try to do this it fail, i don't know if i'm doing something wrong, please help me !!
The NetworkTopic class hasnt been assigned an id. you must use the setId method or consider consider one of the other id strategies
2.2.3.1. Generating the identifier property
NetworkTopic networkTopic = new NetworkTopic();
networkTopic.setNetworkId(networkId);
networkTopic.setTopicId(topicId);
networkTopic.setNetwork(network);
networkTopic.setTopic(topic);
LOG.debug("userTopicService addObjSubscriber x networkId="+networkId+", topicId="+topicId);
networkTopicDao.saveOrUpdate(networkTopic);
Here,you must call the method setId, and set the value manually, because your id generator is "assigned", and that means you must assigned manually every time before you insert or update your data!

Categories

Resources