NetBeans Forums

 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister   ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 
  

Using calculated properties of an entity - basic persitence design question

 
Post new topic   Reply to topic    NetBeans Forums -> Java EE Users
View previous topic :: View next topic  
Author Message
qkrijger



Joined: 27 Jul 2009
Posts: 9

PostPosted: Thu Jul 30, 2009 11:02 am    Post subject: Using calculated properties of an entity - basic persitence design question Reply with quote

Hi all,

I am having some serious trouble in finding out how this works. Maybe I'm not Googling correctly, but I have spent many hours already on this problem and I'm not getting anywhere. I am also reasonably sure I have checked out all the Netbeans tutorials on this matter, but alas. So I guess, I could do with some help.

This is really a basic (beginner?) question about persistence. As a side note: I am using Netbeans 6.7

I am running a database and all my tables have corresponding entity classes. I have a GUI in which I want to display a table from the database, together with some calculated values.

I'll make the setup as simple as possible. Take the simple database created by

Code:
CREATE DATABASE administration;
USE administration;
CREATE TABLE customers (
  id INT NOT NULL AUTO_INCREMENT,
  firstname VARCHAR(50) NOT NULL,
  surname VARCHAR(50 NOT NULL,
  PRIMARY KEY(id)
) ENGINE=INNODB;

INSERT INTO customers (firstname, surname)
  VALUES ('John', 'Adams'), ('Caroline', 'Nixon')


Based on this database, Netbeans creates an entity class
Code:
@Entity
@Table(name = "customers")
@NamedQueries({
  @NamedQuery(name = "Customers.findAll", query = "SELECT c FROM Customers c"),
  @NamedQuery(name = "Customers.findById", query = "SELECT c FROM Customers c WHERE c.id = :id"),
  @NamedQuery(name = "Customers.findByFirstname", query = "SELECT c FROM Customers c WHERE c.firstname= :firstname"),
  @NamedQuery(name = "Customers.findBySurname", query = "SELECT c FROM Customers c WHERE c.surname= :surname")})
public class Customers implements Serializable {
  @Transient
  private PropertyChangeSupport changeSupport = new PropertyChangeSupport(this);
  private static final long serialVersionUID = 1L;
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Basic(optional = false)
  @Column(name = "id")
  private Integer id;
  @Basic(optional = false)
  @Column(name = "firstname")
  private String firstname;
  @Basic(optional = false)
  @Column(name = "surname")
  private String surname;

  // CONSTRUCTORS
  // GET AND SET METHODS
  // A FEW SIMPLE @override METHODS

  public void addPropertyChangeListener(PropertyChangeListener listener) {
    changeSupport.addPropertyChangeListener(listener);
  } public void removePropertyChangeListener(PropertyChangeListener listener) {
    changeSupport.removePropertyChangeListener(listener);
  }
}


Now, using the Netbeans GUI tools I create a JTable with values bound to Customers. This works fine: the apllication reads the database and displays correct values in the table (however, externally making a change in the database is not updated in the table, nor are changes in the table sent to the database, but that is a different matter - gonna work on that after this).

The next step is creating a calculated property, say "private String adressee" which is calculated by Java code the be for example "C. Nixon" or "J. Adams". (This is my question: what is the correct way of implementing something like this, so that it is updated in the table when firstname or surname are altered?) Now the problems start. Simply defining this property gives errors, because it is automatically interpreted as a persistent value. So the apllication does an SQL query interpreting 'adressee' as a column, which of course results in an error. Alternatively, I can define 'adressee' as @Transient. Now, the application compiles and runs, but 'adressee' is never updated in the table. Note that I update it manually: that is, I have the program listen to PropertyChange for surname and firstname, and the generate the correct value for adressee. This works, but is not reflected in the table. I have also tried to refresh() the JTableBinding when a PropertyChange occurs, but this returns a NullPointerException. Moreover, even if that should work, I am convinced there must be a way more elegant method.

I anyone would be so kind as to enlighten me, please do!

Thanks



p.s. this is a cross-post form the java forum (http://forums.sun.com/thread.jspa?messageID=10780748), where I did not get an answer for several days. I promise to cross-reference any answers.


Last edited by qkrijger on Fri Jul 31, 2009 10:48 am; edited 1 time in total
Back to top
Melongo Annabel
Posted via mailing list.





PostPosted: Thu Jul 30, 2009 11:38 pm    Post subject: Using calculated properties of an entity - basic persitence design question Reply with quote

I think you should work with events to resolve your problem. I would recommend you put event listeners on the table cells you want to monitor so that whenever those cells are changes, the changes are reflected on your calculated cell. Here's a tutorial that might be helpful: http://java.sun.com/docs/books/tutorial/uiswing/events/tablemodellistener.html


From: qkrijger <address-removed>
To: address-removed
Sent: Thursday, July 30, 2009 6:03:14 AM
Subject: [nbj2ee] Using calculated properties of an entity - basic persitence design question

Hi all,



I am having some serious trouble in finding out how this works. Maybe I'm not Googling correctly, but I have spent many hours already on this problem and I'm not getting anywhere. I am also reasonably sure I have checked out all the Netbeans tutorials on this matter, but alas. So I guess, I could do with some help.



This is really a basic (beginner?) question about persistence. As a side note: I am using Netbeans 6.7



I am running a database and all my tables have corresponding entity classes. I have a GUI in which I want to display a table from the database, together with some calculated values.



I'll make the setup as simple as possible. Take the simple database created by




Code:
CREATE DATABASE administration;

USE administration;

CREATE TABLE customers (

id INT NOT NULL AUTO_INCREMENT,

firstname VARCHAR(50) NOT NULL,

surname VARCHAR(50 NOT NULL,

PRIMARY KEY(id)

) ENGINE=INNODB;



INSERT INTO customers (firstname, surname)

VALUES ('John', 'Adams'), ('Caroline', 'Nixon')





Based on this database, Netbeans creates an entity class


Code:
@Entity

@Table(name = "customers")

@NamedQueries({

@NamedQuery(name = "Customers.findAll", query = "SELECT c FROM Customers c"),

@NamedQuery(name = "Customers.findById", query = "SELECT c FROM Customers c WHERE c.id = :id"),

@NamedQuery(name = "Customers.findByFirstname", query = "SELECT c FROM Customers c WHERE c.firstname= :firstname"),

@NamedQuery(name = "Customers.findBySurname", query = "SELECT c FROM Customers c WHERE c.surname= :surname")})

public class Customers implements Serializable {

@Transient

private PropertyChangeSupport changeSupport = new PropertyChangeSupport(this);

private static final long serialVersionUID = 1L;

@Id

@GeneratedValue(strategy = GenerationType.IDENTITY)

@Basic(optional = false)

@Column(name = "id")

private Integer id;

@Basic(optional = false)

@Column(name = "firstname")

private String firstname;

@Basic(optional = false)

@Column(name = "surname")

private String surname;



// CONSTRUCTORS

// GET AND SET METHODS

// A FEW SIMPLE @override METHODS



public void addPropertyChangeListener(PropertyChangeListener listener) {

changeSupport.addPropertyChangeListener(listener);

} public void removePropertyChangeListener(PropertyChangeListener listener) {

changeSupport.removePropertyChangeListener(listener);

}

}





Now, using the Netbeans GUI tools I create a JTable with values bound to Customers. This works fine: the apllication reads the database and displays correct values in the table (however, externally making a change in the database is not updated in the table, nor are changes in the table sent to the database, but that is a different matter - gonna work on that after this).



The next step is creating a calculated property, say "private String adressee" which is calculated by Java code the be for example "C. Nixon" or "J. Adams". (This is my question: what is the correct way of implementing something like this, so that it is updated in the table when firstname or surname are altered?) Now the problems start. Simply defining this property gives errors, because it is automatically interpreted as a persistent value. So the apllication does an SQL query interpreting 'adressee' as a column, which of course results in an error. Alternatively, I can define 'adressee' as @Transient. Now, the application compiles and runs, but 'adressee' is never updated in the table. Note that I update it manually: that is, I have the program listen to PropertyChange for surname and firstname, and the generate the correct value for adressee. This works, but is not reflected in the table. I have also tried to refresh() the JTableBinding when a PropertyChange occurs, but th
is returns a NullPointerException. Moreover, even if that should work, I am convinced there must be a way more elegant method.



I anyone would be so kind as to enlighten me, please do!



Thanks







p.s. this is a cross-post form the java forum (http://forums.sun.com/edit!default.jspa?messageID=10778727), where I did not get an answer for several days. I promise to cross-reference any answers.
Back to top
qkrijger



Joined: 27 Jul 2009
Posts: 9

PostPosted: Fri Jul 31, 2009 10:40 am    Post subject: Re: Using calculated properties of an entity - basic persitence design question Reply with quote

Melongo Annabel wrote:
I think you should work with events to resolve your problem. I would recommend you put event listeners on the table cells you want to monitor so that whenever those cells are changes, the changes are reflected on your calculated cell. Here's a tutorial that might be helpful: http://java.sun.com/docs/books/tutorial/uiswing/events/tablemodellistener.html.


Thanks for your answer. The method you propose is not difficult to code and should work for sure. I'll start on implementing it. The reason I did not do this yet is that I assumed there would be a more elegant method:

NETBEANS
Persisitent properties can be used in elements like a JTable in such an efficient way. Having to hard code Listeners on cells is something I had not expected to be necessary. If there is some functionality in the GUI builder related to this, I would love to hear about it.

PERSISTENCE
On the other hand, should there not be an annotation in persistence that is between Transient and Column? I would expect an annotation for properties that depend on persistent values, but are not represented in for instance a database table themselves. Something like
Code:

// within an Entity class, where columns with names naam_1 ... naam_n are defined at least
@Calculated (name = "name", vars = ("naam_1", "naam_2", ..., "naam_n")
private Class calcProp;
// ...
@Calculation
private Class method_name(Class naam_1, Class naam_2, ... Class naam_n) {
  // method code that always returns a valid value, maybe persistence should automatically return null in case of Exceptions or errors.
}

Such a property could be kept up to date automatically and be used by programs efficiently (for instance, Netbeans would have no problem to put this in a JTable without much coding for the user). Do I understand correctly that something like this does not exist? So, what is normally done for calculated values (what design should one use)? If everything always is hard-coded I think I'm gonna open a ticket for this. But since I am a noob, I first have to know if I am correct in this.
Back to top
qkrijger



Joined: 27 Jul 2009
Posts: 9

PostPosted: Sat Aug 01, 2009 12:26 pm    Post subject: Reply with quote

Somehow, retrying my first technique worked. Maybe it is because I am now using Hibernate, set to Eager (not Lazy, which gave me compiling errors!). For future reference, here is how I did it.

The MySQL table is called 'relaties'. 'contactpersoon' is a value which I want to calculate from several other values from this table and its related tables.

I use Netbeans to create entity classes from database. One of which is Relaties:
Code:
@Entity
@Table(name = "relaties", catalog = "TK", schema = "")
public class Relaties implements Serializable {
  @Transient
  private PropertyChangeSupport changeSupport = new PropertyChangeSupport(this);
  private static final long serialVersionUID = 1L;
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Basic(optional = false)
  @Column(name = "id")
  private Integer id;
  // AND MANY OTHER COLUMNS, THE USUAL ENTITY CODE

  @Transient
  private String contactpersoon;

  public String getContactpersoon() {
    return contactpersoon;
  }

  public void setContactpersoon(String contactpersoon) {
    String oldContactpersoon = this.contactpersoon;
    this.contactpersoon = contactpersoon;
    changeSupport.firePropertyChange("contactpersoon", oldContactpersoon, contactpersoon);
  }

  public void genContactpersoon() {
    // calculation code - note that I had to catch NullPointerExceptions for Columns without @Basic(optional = false)
    this.setContactpersoon(s);
  }

  public void addPropertyChangeListener(PropertyChangeListener listener) {
    changeSupport.addPropertyChangeListener(listener);
  }

  public void removePropertyChangeListener(PropertyChangeListener listener) {
    changeSupport.removePropertyChangeListener(listener);
  }
}



I now make another class, in which I put everything I think Relaties should do itself, but I can't put in there because of compilation errors (my bad?):
Code:

public class RelatiesHelper implements PropertyChangeListener {

  public void init(Relaties r) {
    r.addPropertyChangeListener(this);
    r.genContactpersoon();
    r.genAdressering();
  }

  public void propertyChange(PropertyChangeEvent evt) {
    if (evt.getPropertyName().equals("achternaam") || evt.getPropertyName().equals("tussenvoegsels") || evt.getPropertyName().equals("voornaam") || evt.getPropertyName().equals("titel")) { // these are column titles of the properties on which 'contactpersoon' depends
      ((Relaties) evt.getSource()).genContactpersoon();
      }
    }
  }
}


I now made a class ViewRelaties, which includes a JTable. The values of this JTable can now be bound in the usual way, including 'contactpersoon':
Code:

public class ViewRelaties
        extends javax.swing.JPanel {

  /** Creates new form ViewRelaties */
  public ViewRelaties() {
    initComponents(); // code to create table and initialize a Relaties-list, bind values etc.

    ListIterator<Relaties> l = this.relatiesList.listIterator();
    RelatiesHelper rh = new RelatiesHelper();
    while (l.hasNext()) {
      rh.init(l.next());
    }
  }

  // THE initComponents() CODE
  private javax.persistence.EntityManager AdminPUEntityManager;
  private javax.persistence.Query relatiesQuery;
  private java.util.List<admin.entities.Relaties> relatiesList;
}


Now, the JTable is updated as should. Hope this helps someone Smile

I still believe this could be done more efficiently with a @calculated annotation as I proposed in my last post. Any thought on this by anyone? (As much as I like to talk to myself, I would appreciate feedback on this particular matter).

Greetings!
Back to top
Display posts from previous:   
Post new topic   Reply to topic    NetBeans Forums -> Java EE Users All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You can attach files in this forum
You can download files in this forum


Powered by phpBB
By use of this website, you agree to the NetBeans Policies and Terms of Use. © 2012, Oracle Corporation and/or its affiliates. Sponsored by Oracle logo