[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Newsgroup Home]
[news.eclipse.rt.eclipselink] Re: @Version field does partially update?

Hi James,

This is the Superclass:
8<-------------------------------------------------
package ch.eugster.colibri.persistence.entities;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;

import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import javax.persistence.Transient;
import javax.persistence.Version;

import org.eclipse.persistence.annotations.ConversionValue;
import org.eclipse.persistence.annotations.Convert;
import org.eclipse.persistence.annotations.ObjectTypeConverter;

@MappedSuperclass
@ObjectTypeConverter(name = "booleanConverter", dataType = java.lang.Short.class, objectType = java.lang.Boolean.class, conversionValues =
{ @ConversionValue(dataValue = "0", objectValue = "false"),
@ConversionValue(dataValue = "1", objectValue = "true") }, defaultObjectValue = "false")
public abstract class AbstractEntity
{
protected static long counter = 0l;

public static boolean DEBUG = true;

protected static void out(String output)
{
if (AbstractEntity.DEBUG)
{
System.out.println(output);
}
}

protected static void err(String error)
{
System.err.println(error);
}

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
protected Long id;

protected long timestamp;

@Convert("booleanConverter")
protected boolean deleted;

@Version
protected int version;

@Transient
protected PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);

public AbstractEntity()
{
}

public Long getId()
{
return this.id;
}

public void setId(Long id)
{
this.propertyChangeSupport.firePropertyChange("id", this.id, this.id = id);
}

public long getTimestamp()
{
return this.timestamp;
}

public void setTimestamp(long timestamp)
{
this.propertyChangeSupport.firePropertyChange("timestamp", this.timestamp,
this.timestamp = timestamp);
}

public boolean isDeleted()
{
return this.deleted;
}

public void setDeleted(boolean deleted)
{
this.propertyChangeSupport.firePropertyChange("deleted", this.deleted,
this.deleted = deleted);
}

public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener)
{
this.propertyChangeSupport.addPropertyChangeListener(propertyName, listener);
}

public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener)
{
this.propertyChangeSupport.removePropertyChangeListener(propertyName, listener);
}

public int getVersion()
{
return this.version;
}

public void setVersion(int version)
{
this.version = version;
}

protected String getString(String string)
{
return string == null ? "" : string;
}

@Override
public int hashCode()
{
if (this.id == null)
return Integer.MIN_VALUE;
else
{
return Integer.MIN_VALUE + this.id.intValue();
}
}

@Override
public boolean equals(Object object)
{
if (object == null) return false;

if (this.getClass().equals(object.getClass()))
{
AbstractEntity bt = (AbstractEntity) object;
return this.hashCode() == bt.hashCode();
}

return false;
}

}
8<-------------------------------------------------


And this is the class that fails to merge after the first merge:

8<-------------------------------------------------
/*
* Created on 17.12.2008
*
* To change the template for this generated file go to
* Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
*/
package ch.eugster.colibri.persistence.entities;

import static javax.persistence.CascadeType.ALL;
import static javax.persistence.FetchType.EAGER;

import java.util.ArrayList;
import java.util.Collection;

import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
@AttributeOverrides(
{
@AttributeOverride(name = "id", column = @Column(name = "tab_id", updatable = false, unique = true)),
@AttributeOverride(name = "version", column = @Column(name = "tab_version")),
@AttributeOverride(name = "timestamp", column = @Column(name = "tab_timestamp")),
@AttributeOverride(name = "deleted", column = @Column(name = "tab_deleted")) })
@Table(name = "colibri_tab")
public class Tab extends AbstractEntity implements Comparable<Tab>
{
@ManyToOne(cascade = ALL)
@JoinColumn(name = "tab_configurable_id", referencedColumnName = "configurable_id")
private Configurable configurable;

@Basic
@Column(name = "tab_name")
private String name;

@Basic
@Column(name = "tab_rows")
private int rows;

@Basic
@Column(name = "tab_cols")
private int cols;

@Basic
@Column(name = "tab_pos")
private int pos;

@OneToMany(cascade = CascadeType.ALL, fetch = EAGER, mappedBy = "tab")
private Collection<Key> keys = new ArrayList<Key>();

public Tab()
{
super();
}

public Tab(Configurable configurable)
{
super();
this.setConfigurable(configurable);
}

public Configurable getConfigurable()
{
return this.configurable;
}

public void setConfigurable(Configurable configurable)
{
this.propertyChangeSupport.firePropertyChange("configurable", this.configurable,
this.configurable = configurable);
}

public String getName()
{
return this.getString(this.name);
}

public void setName(String name)
{
this.propertyChangeSupport.firePropertyChange("name", this.name, this.name = name);
}

public int getRows()
{
return this.rows;
}

public void setRows(int rows)
{
this.propertyChangeSupport.firePropertyChange("rows", this.rows, this.rows = rows);
}

public int getCols()
{
return this.cols;
}

public void setCols(int cols)
{
this.propertyChangeSupport.firePropertyChange("cols", this.cols, this.cols = cols);
}

public int getPos()
{
return this.pos;
}

public void setPos(int pos)
{
this.propertyChangeSupport.firePropertyChange("pos", this.pos, this.pos = pos);
}

public Collection<Key> getKeys()
{
return this.keys;
}

public void addKey(Key key)
{
if (key != null)
if (!this.keys.contains(key))
this.propertyChangeSupport
.firePropertyChange("keys", this.keys, this.keys.add(key));
}

public void removeKey(Key key)
{
if (key != null)
if (this.keys.contains(key))
this.propertyChangeSupport.firePropertyChange("keys", this.keys, this.keys
.remove(key));
}

public void setKeys(Collection<Key> keys)
{
this.propertyChangeSupport.firePropertyChange("keys", this.keys, this.keys = keys);
}

public int compareTo(Tab other)
{
return other.getPos() - this.getPos();
}
}
8<-------------------------------------------------


And this is a class that merges successfully:

8<-------------------------------------------------
/*
* Created on 17.12.2008
*
* To change the template for this generated file go to
* Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
*/
package ch.eugster.colibri.persistence.entities;

import static javax.persistence.CascadeType.ALL;

import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@AttributeOverrides(
{
@AttributeOverride(name = "id", column = @Column(name = "stock_id", updatable = false, unique = true)),
@AttributeOverride(name = "version", column = @Column(name = "stock_version")),
@AttributeOverride(name = "timestamp", column = @Column(name = "stock_timestamp")),
@AttributeOverride(name = "deleted", column = @Column(name = "stock_deleted")) })
@Table(name = "colibri_stock")
public class Stock extends AbstractEntity
{
@ManyToOne(cascade = ALL)
@JoinColumn(name = "stock_salespoint_id", referencedColumnName = "salespoint_id")
private Salespoint salespoint;

@ManyToOne(cascade = ALL)
@JoinColumn(name = "stock_payment_type_id", referencedColumnName = "payment_type_id")
private PaymentType paymentType;

@Basic
@Column(name = "stock_amount")
private double amount;

@Basic
@Column(name = "stock_variable")
private boolean variable;

public Stock()
{
super();
}

public Stock(Salespoint salespoint)
{
super();
this.setSalespoint(salespoint);
}

public Stock(Salespoint salespoint, PaymentType paymentType)
{
this.setSalespoint(salespoint);
this.setPaymentType(paymentType);
}

public Salespoint getSalespoint()
{
return this.salespoint;
}

public void setSalespoint(Salespoint salespoint)
{
this.propertyChangeSupport.firePropertyChange("salespoint", this.salespoint,
this.salespoint = salespoint);
}

public PaymentType getPaymentType()
{
return this.paymentType;
}

public void setPaymentType(PaymentType paymentType)
{
this.propertyChangeSupport.firePropertyChange("paymentType", this.paymentType,
this.paymentType = paymentType);
}

public double getAmount()
{
return this.amount;
}

public void setAmount(double amount)
{
this.propertyChangeSupport.firePropertyChange("amount", this.amount, this.amount = amount);
}

public boolean isVariable()
{
return this.variable;
}

public void setVariable(boolean variable)
{
this.propertyChangeSupport.firePropertyChange("variable", this.variable,
this.variable = variable);
}

}
8<-------------------------------------------------


The code to update the objects is in the editor and as follows:

8<-------------------------------------------------
@Override
public void doSave(IProgressMonitor monitor)
{
if (this.validate())
{
this.saveValues();
AbstractEntityEditorInput input = (AbstractEntityEditorInput) this.getEditorInput();
AbstractEntity entity = input.getEntity();
try
{
if (input.hasParent())
{
Repository.getCurrent().store(entity, true);
Repository.getCurrent().refresh(input.getParent());
}
else
Repository.getCurrent().store(entity);
this.setDirty(false);
this.scrolledForm.setText(this.getText());
this.updateControls();

}
catch (PersistenceException e)
{
if (e.getErrorCode().equals(PersistenceException.ErrorCode.SQL_4002))
{
Shell shell = this.getSite().getShell();
Message msg = this.getMessage(e.getErrorCode());
new MessageDialog(shell, msg.getTitle(), null, msg.getMessage(),
MessageDialog.WARNING, new String[]
{ Messages.AbstractEntityEditor_ok }, 0).open();

this.setFocus(msg.getControl());
}
}
}
}

The called method of the previous method (store):


public void store(AbstractEntity entity, boolean silent, boolean updateTimestamp)
throws PersistenceException
{
try
{
boolean tx = this.beginTransaction();
WriteType type = this.doStore(entity, updateTimestamp);
if (tx) this.commitTransaction();
if (!silent) this.repository.fireWriteDatabaseEvent(new WriteEvent(entity, type));
}
catch (Exception e)
{
e.printStackTrace();

Throwable cause = e.getCause();
if (cause instanceof DatabaseException)
{
DatabaseException de = (DatabaseException) cause;
throw new PersistenceException(de);
}
else if (cause instanceof javax.persistence.OptimisticLockException)
{
org.eclipse.persistence.exceptions.OptimisticLockException ole = (org.eclipse.persistence.exceptions.OptimisticLockException) cause
.getCause();
throw new PersistenceException(ole);
}
}
finally
{
this.rollbackTransaction();
}
}
8<-------------------------------------------------

and the code that updates (merges) the object is as follows:


8<-------------------------------------------------
	private WriteType doStore(AbstractEntity entity, boolean updateTimestamp)
	{
		if (updateTimestamp)
			entity.setTimestamp(GregorianCalendar.getInstance().getTimeInMillis());
		
		if (entity.getId() == null)
		{
			this.entityManager.persist(entity);
			return WriteType.INSERT;
		}
		else
		{
			this.entityManager.merge(entity);
			return WriteType.UPDATE;
		}
	}
8<-------------------------------------------------
	
I hope that that helps you to see into my code...

Thank you

Christian