NetBeans Forums
| View previous topic :: View next topic |
| Author |
Message |
qkrijger
Joined: 27 Jul 2009 Posts: 9
|
Posted: Thu Jul 30, 2009 11:02 am Post subject: 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 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.
|
Posted: Thu Jul 30, 2009 11:38 pm Post subject: Using calculated properties of an entity - basic persitence design question |
|
|
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
|
Posted: Fri Jul 31, 2009 10:40 am Post subject: Re: Using calculated properties of an entity - basic persitence design question |
|
|
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
|
Posted: Sat Aug 01, 2009 12:26 pm Post subject: |
|
|
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
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 |
|
 |
|
|
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
|
|