From ad82958d03b771c36bcfa0a2a8db3b222dac4fb9 Mon Sep 17 00:00:00 2001 From: Martin Goik <goik@hdm-stuttgart.de> Date: Mon, 11 Apr 2016 22:01:57 +0200 Subject: [PATCH] Correcting entity and table definitions --- Doc/Sda2/jpa.xml | 293 ++++++++++-------- .../src/main/java/hibintro/v5/User.java | 3 - .../src/main/java/hibintro/v6/Project.java | 31 +- .../src/main/java/hibintro/v7/User.java | 15 +- 4 files changed, 173 insertions(+), 169 deletions(-) diff --git a/Doc/Sda2/jpa.xml b/Doc/Sda2/jpa.xml index 6d7c532f6..8139bcaa4 100644 --- a/Doc/Sda2/jpa.xml +++ b/Doc/Sda2/jpa.xml @@ -1012,19 +1012,20 @@ public class User { statements containing an attribute <code>selected</code> <coref linkend="attributeSelected"/>:</para> - <programlisting language="none">CREATE TABLE User ( - uid VARCHAR(255) NOT NULL PRIMARY KEY, - cname VARCHAR(255), - <emphasis role="bold">selected</emphasis> <co xml:id="attributeSelected"/> BIT NOT NULL, - ) </programlisting> + <programlisting language="sql">CREATE TABLE User ( + uid VARCHAR(255) NOT NULL PRIMARY KEY, + cname VARCHAR(255), + <emphasis role="bold">selected</emphasis> <co xml:id="attributeSelected"/> BIT NOT NULL, +) </programlisting> <para>If we just annotate a Java class with an <classname>javax.persistence.Entity</classname> Annotation all properties of the class in question will be mapped. A <xref linkend="glo_JPA"/> framework of course cannot distinguish between transient and persistent properties. If we want a property to be - transient we have to add a - <classname>javax.persistence.Transient</classname> annotation:</para> + transient we have to add a <classname + xlink:href="http://docs.oracle.com/javaee/7/api/javax/persistence/Transient.html">javax.persistence.Transient</classname> + annotation:</para> <informaltable border="1"> <colgroup width="6%"/> @@ -1050,20 +1051,22 @@ public class User { <tr> <td valign="top"><emphasis role="bold">SQL</emphasis></td> - <td><programlisting language="none">CREATE TABLE User ( - uid VARCHAR(255) NOT NULL PRIMARY KEY, - cname VARCHAR(255) - ) </programlisting></td> + <td><programlisting language="sql">CREATE TABLE User ( + uid VARCHAR(255) NOT NULL PRIMARY KEY, + cname VARCHAR(255) +) </programlisting></td> </tr> </informaltable> - <para>The <classname>javax.persistence.Transient</classname> annotation - inhibits the mapping of our property <code>selected</code>.</para> + <para>The <classname + xlink:href="http://docs.oracle.com/javaee/7/api/javax/persistence/Transient.html">javax.persistence.Transient</classname> + annotation inhibits the mapping of our property + <code>selected</code>.</para> <caution> <para>When loading a <classname>hibintro.v3.User</classname> instance - from a database the transient property's value is of course entirely - determined by the constructor.</para> + from a database all transient property values are of course entirely + determined by the default constructor.</para> </caution> </section> @@ -1079,8 +1082,11 @@ public class User { <para>The <code>cname</code> property however may be null. Sometimes we want to ensure the corresponding database attributes to be set, at least carrying an empty string value. This can be achieved by adding a - <classname>javax.persistence.Column</classname><code>(nullable = - false)</code> annotation:</para> + <classname + xlink:href="http://docs.oracle.com/javaee/7/api/javax/persistence/Column.html">javax.persistence.Column</classname> + <option + xlink:href="http://docs.oracle.com/javaee/7/api/javax/persistence/Column.html#nullable--">(nullable + = false)</option> annotation:</para> <informaltable border="1"> <colgroup width="6%"/> @@ -1090,32 +1096,33 @@ public class User { <tr> <td valign="top"><emphasis role="bold">Java</emphasis></td> - <td valign="top"><programlisting language="none">package hibintro.v4; - - ... - @Entity public class User { - - String cname; - <emphasis role="bold">@Column(nullable = false)</emphasis> public String getCname() { - return cname; - } - ...</programlisting></td> + <td valign="top"><programlisting language="java">package hibintro.v4; + ... +@Entity public class User { + ... + String cname; + <emphasis role="bold"><classname + xlink:href="http://docs.oracle.com/javaee/7/api/javax/persistence/Column.html">@Column</classname>(<option + xlink:href="http://docs.oracle.com/javaee/7/api/javax/persistence/Column.html#nullable--">nullable</option> = false)</emphasis> public String getCname() { + return cname; + } + ...</programlisting></td> </tr> <tr> <td valign="top"><emphasis role="bold">SQL</emphasis></td> - <td><programlisting language="none">CREATE TABLE User ( - uid VARCHAR(255) NOT NULL PRIMARY KEY, - cname VARCHAR(255) <emphasis role="bold">NOT NULL</emphasis> <co + <td><programlisting language="sql">CREATE TABLE User ( + uid VARCHAR(255) NOT NULL PRIMARY KEY, + cname VARCHAR(255) <emphasis role="bold">NOT NULL</emphasis> <co xml:id="cnameDatabaseNotNull"/> - )</programlisting></td> +)</programlisting></td> </tr> </informaltable> <para>This results in a corresponding database constraint <coref - linkend="cnameDatabaseNotNull"/>. Attempting to store instances with - null values now fails:</para> + linkend="cnameDatabaseNotNull"/>. Attempts to store instances with null + values now fail:</para> <informaltable border="1"> <colgroup width="6%"/> @@ -1129,39 +1136,28 @@ public class User { ... public class PersistSingleUser { - final Transaction transaction = session.beginTransaction(); - { - final User u = new User("goik", null); - session.save(u); - } - transaction.commit(); ...</programlisting></td> + em.getTransaction().begin(); + { + em.persist(new User("goik", "Martin Goik")); + } + em.getTransaction().commit();</programlisting></td> </tr> <tr> <td valign="top"><emphasis role="bold">Log</emphasis></td> - <td><programlisting language="none">Hibernate: - insert - into - User - (cname, uid) - values - (?, ?) - ... - WARN: SQL Error: 1048, SQLState: 23000 - Feb 13, 2013 9:38:32 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions - ERROR: Column 'cname' cannot be null - Exception in thread "main" org.hibernate.exception.ConstraintViolationException: Column 'cname' cannot be null - ... - <emphasis role="bold">Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'cname' cannot be null</emphasis> - ...</programlisting></td> + <td><programlisting language="none">Exception in thread "main" javax.persistence.PersistenceException: + org.hibernate.PropertyValueException: <emphasis role="bold">not-null property references a null or transient value</emphasis> : +hibintro.v4.User.cname + at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1692) + ... + at hibintro.v4.PersistSingleUser.main(PersistSingleUser.java:22)</programlisting></td> </tr> </informaltable> - <para>The exception is thrown by the <trademark + <para>The database constraint violation causes the <trademark xlink:href="http://www.oracle.com/technetwork/java/javase/jdbc">JDBC</trademark> - driver as the result of a database constraint violation but not by the - hibernate framework itself prior to attempting the insert.</para> + driver to throw this exception.</para> </section> <section xml:id="mappingKeys"> @@ -1169,36 +1165,48 @@ public class User { <para>Frequently we need more than just a primary key. Starting from <classname>hibintro.v4.User</classname> we may want to add a property - <code>uidNumber</code>. This is a common requirement: On UNIX type - operation systems for example each user does have both a unique login - name (like <quote>goik</quote>) and a unique numerical value (like + <code>uidNumber</code> adding a common requirement: On UNIX type + operation systems each user does have both a unique login name (like + <quote>goik</quote>) and a unique numerical value (like <quote>123</quote>). We choose our primary key to be numeric <coref linkend="uidNumberIsPrimaryKey"/>and the login name to become a second candidate key <coref linkend="uidIsUnique"/>:</para> - <programlisting language="none">package hibintro.v5; - ... - @Entity - @Table(uniqueConstraints={@UniqueConstraint(columnNames={"uid"})}) <co + <programlisting language="java">package hibintro.v5; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.persistence.UniqueConstraint; + +@Entity +@Table(uniqueConstraints={<classname + xlink:href="http://docs.oracle.com/javaee/7/api/javax/persistence/UniqueConstraint.html">@UniqueConstraint</classname>(<option + xlink:href="http://docs.oracle.com/javaee/7/api/javax/persistence/UniqueConstraint.html#columnNames--">columnNames</option>={"uid"})}) <co xml:id="uidIsUnique"/> - public class User { +public class User { - int uidNumber; - @Id <co xml:id="uidNumberIsPrimaryKey"/> public int getUidNumber() { - return uidNumber; - } - public void setUidNumber(int uidNumber) { - this.uidNumber = uidNumber; - } + int uidNumber; + @Id <co xml:id="uidNumberIsPrimaryKey"/> + public int getUidNumber() { return uidNumber; } + public void setUidNumber(int uidNumber) { this.uidNumber = uidNumber; } - String uid; - public String getUid() { - return uid; - } - public void setUid(String uid) { - this.uid = uid; - } - ...</programlisting> + String uid; + + /** + * @return The user's unique login name e.g. "goik" + */ + @Column(nullable=false) + public String getUid() { return uid; } + + /** + * @param uid, See {@link #getUid()}. + */ + public void setUid(String uid) { this.uid = uid; } + + ... +}</programlisting> <para>Notice the slight difference: The property <code>uid</code> may need a @@ -1218,23 +1226,23 @@ public class User { values but attributes only appearing in UNIQUE declarations may become <code>NULL</code>.</para> - <para>The <abbrev + <para>The resulting <abbrev xlink:href="https://en.wikipedia.org/wiki/Data_definition_language">DDL</abbrev> reads:</para> <programlisting language="none">CREATE TABLE User ( - uidNumber INT NOT NULL PRIMARY KEY, - cname VARCHAR(255) NOT NULL, - uid VARCHAR(255) NOT NULL UNIQUE - )</programlisting> + uidNumber INT NOT NULL PRIMARY KEY, + cname VARCHAR(255) NOT NULL, + uid VARCHAR(255) NOT NULL UNIQUE +)</programlisting> </section> <section xml:id="sect_ComposedKeys"> <title>Composed keys</title> - <para>Composed candidate keys are sometimes referred to as business - keys. The underlying logic defines which objects are considered to be - identical based on their values.</para> + <para>Composed candidate keys are often business keys. The underlying + logic defines which objects are considered to be identical based on + their values.</para> <para>As an example, we consider a company having several departments. Regarding projects he following business rules shall apply:</para> @@ -1279,37 +1287,41 @@ public class User { <tr> <td valign="top"><emphasis role="bold">Java</emphasis></td> - <td valign="top"><programlisting language="none">package hibintro.v6; - ... - @Entity - @Table(uniqueConstraints={@UniqueConstraint(columnNames={"name", "department"})}) <co + <td valign="top"><programlisting language="java">package hibintro.v6; + ... +@Entity +@Table(uniqueConstraints={<classname + xlink:href="http://docs.oracle.com/javaee/7/api/javax/persistence/UniqueConstraint.html">@UniqueConstraint</classname>(columnNames={"name", "department"})}) <co xml:id="projectBusinessKey"/> - public class Project { - int id; - @Id <co xml:id="projectPrimaryKeyDefinition"/> public int getId() {return id;} - protected void setId(int id) {this.id = id;} - - String name; - @Column(nullable=false) public String getName() {return name;} - public void setName(String name) {this.name = name;} - - int department; - @Column(nullable=false) - public int getDepartment() {return department;} - public void setDepartment(int department) {this.department = department;} - ...</programlisting></td> +public class Project { + + int id; + @Id <co xml:id="projectPrimaryKeyDefinition"/> + public int getId() { return id; } + protected void setId(int id) { this.id = id; } + + String name; + @Column(nullable=false) + public String getName() { return name; } + public void setName(String name) { this.name = name; } + + int department; + @Column(nullable=false) + public int getDepartment() { return department; } + public void setDepartment(int department) { this.department = department; } + ... +}</programlisting></td> </tr> <tr> <td valign="top"><emphasis role="bold">Sql</emphasis></td> - <td><programlisting language="none">CREATE TABLE Project ( - id int(11) NOT NULL PRIMARY KEY <coref - linkend="projectPrimaryKeyDefinition"/>, - department int(11) NOT NULL, - name varchar(255) NOT NULL, - UNIQUE KEY name (name,department) <coref linkend="projectBusinessKey"/> - )</programlisting></td> + <td><programlisting language="sql">CREATE TABLE Project ( + id int(11) NOT NULL PRIMARY KEY <coref linkend="projectPrimaryKeyDefinition"/>, + department int(11) NOT NULL, + name varchar(255) NOT NULL, + UNIQUE KEY name (name,department) <coref linkend="projectBusinessKey"/> +)</programlisting></td> </tr> </informaltable> @@ -1388,32 +1400,49 @@ public class User { <tr> <td valign="top"><emphasis role="bold">Java</emphasis></td> - <td valign="top"><programlisting language="none">package hibintro.v7; - ... - @Entity - @Table(uniqueConstraints={@UniqueConstraint(columnNames={"uid"})}) - <emphasis role="bold">@org.hibernate.annotations.Table(</emphasis> <co + <td valign="top"><programlisting language="java">package hibintro.v7; +... +@Entity +@Table(uniqueConstraints={@UniqueConstraint(name="uidKey", columnNames={"uid"})}, + <emphasis role="bold">indexes = {<classname + xlink:href="http://docs.oracle.com/javaee/7/api/javax/persistence/Index.html">@Index</classname>(<option + xlink:href="http://docs.oracle.com/javaee/7/api/javax/persistence/Index.html#name--">name</option> = "byCname", <option + xlink:href="http://docs.oracle.com/javaee/7/api/javax/persistence/Index.html#columnList--">columnList</option>="cname", <option + xlink:href="http://docs.oracle.com/javaee/7/api/javax/persistence/Index.html#unique--">unique</option> = false)}</emphasis> <co xml:id="hibernateExtensionIndex"/> - <emphasis role="bold">appliesTo="User", - indexes = {@Index(name = "findCname", columnNames = {"cname"})})</emphasis> - public class User { - ... - String cname; - @Column(nullable = false) public String getCname() { return cname;} - public void setCname(String cname) {this.cname = cname;} - ...</programlisting></td> +) +public class User { + + int uidNumber; + @Id + public int getUidNumber() { return uidNumber; } + public void setUidNumber(int uidNumber) { this.uidNumber = uidNumber; } + + String uid; + /** + * @return The user's unique login name e.g. "goik" + */ + @Column(nullable=false) + public String getUid() { return uid; } + + /** + * @param uid See {@link #getUid()}. + */ + public void setUid(String uid) { this.uid = uid; } + ... +}</programlisting></td> </tr> <tr> <td valign="top"><emphasis role="bold">Sql</emphasis></td> - <td><programlisting language="none">CREATE TABLE User ( - uidNumber INT NOT NULL PRIMARY KEY, - cname VARCHAR(255) NOT NULL, - uid VARCHAR(255) NOT NULL UNIQUE - ); + <td><programlisting language="sql">CREATE TABLE User ( + uidNumber INT NOT NULL PRIMARY KEY, + cname VARCHAR(255) NOT NULL, + uid VARCHAR(255) NOT NULL UNIQUE +); - CREATE INDEX findCname ON User (cname ASC);</programlisting></td> +CREATE INDEX findCname ON User (cname ASC);</programlisting></td> </tr> </informaltable> </section> diff --git a/ws/eclipse/HibIntro/src/main/java/hibintro/v5/User.java b/ws/eclipse/HibIntro/src/main/java/hibintro/v5/User.java index e72106a8b..95a51d846 100644 --- a/ws/eclipse/HibIntro/src/main/java/hibintro/v5/User.java +++ b/ws/eclipse/HibIntro/src/main/java/hibintro/v5/User.java @@ -44,9 +44,6 @@ public class User { */ public void setCname(String cname) { this.cname = cname; } - /** - * Hibernate/JPA require a default constructor - */ protected User() {} /** diff --git a/ws/eclipse/HibIntro/src/main/java/hibintro/v6/Project.java b/ws/eclipse/HibIntro/src/main/java/hibintro/v6/Project.java index 34bfde630..1ea0b7c33 100644 --- a/ws/eclipse/HibIntro/src/main/java/hibintro/v6/Project.java +++ b/ws/eclipse/HibIntro/src/main/java/hibintro/v6/Project.java @@ -14,36 +14,23 @@ import javax.persistence.UniqueConstraint; public class Project { int id; - /** - * @return The object's immutable database id - */ + @Id - public int getId() { - return id; - } - protected void setId(int id) { - this.id = id; - } + public int getId() { return id; } + protected void setId(int id) { this.id = id; } String name; @Column(nullable=false) - public String getName() { - return name; - } - public void setName(String name) { - this.name = name; - } + public String getName() { return name; } + public void setName(String name) { this.name = name; } int department; @Column(nullable=false) - public int getDepartment() { - return department; - } - public void setDepartment(int department) { - this.department = department; - } + public int getDepartment() { return department; } + public void setDepartment(int department) { this.department = department; } + + protected Project() {} - public Project() {} public Project(String name, int department) { setName(name); setDepartment(department); diff --git a/ws/eclipse/HibIntro/src/main/java/hibintro/v7/User.java b/ws/eclipse/HibIntro/src/main/java/hibintro/v7/User.java index 3ef35d144..6ba8e91d3 100644 --- a/ws/eclipse/HibIntro/src/main/java/hibintro/v7/User.java +++ b/ws/eclipse/HibIntro/src/main/java/hibintro/v7/User.java @@ -19,23 +19,18 @@ public class User { int uidNumber; @Id - public int getUidNumber() { - return uidNumber; - } + public int getUidNumber() { return uidNumber; } public void setUidNumber(int uidNumber) { this.uidNumber = uidNumber; } String uid; - /** - * * @return The user's unique login name e.g. "goik" */ @Column(nullable=false) public String getUid() { return uid; } /** - * @param uid - * See {@link #getUid()}. + * @param uid See {@link #getUid()}. */ public void setUid(String uid) { this.uid = uid; } @@ -48,14 +43,10 @@ public class User { public String getCname() { return cname; } /** - * @param cname - * See {@link #getCname()}. + * @param cname See {@link #getCname()}. */ public void setCname(String cname) { this.cname = cname; } - /** - * Hibernate/JPA require a default constructor - */ protected User() {} /** -- GitLab