diff --git a/Doc/Sd1/inheritance.xml b/Doc/Sd1/inheritance.xml index 1b7fb67b39e99c76f271747baab7f364ec5ad9c2..6c3735b40c4dc3e8539366353c3dbfd2875c6ad8 100644 --- a/Doc/Sd1/inheritance.xml +++ b/Doc/Sd1/inheritance.xml @@ -1174,7 +1174,9 @@ public class Rectangle </section> <section xml:id="sd1_inherit_sect_instanceOf"> - <title>The <code language="java">instanceOf</code> operator</title> + <title>The <code language="java" + xlink:href="https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.20.2">instanceof</code> + operator</title> <figure xml:id="sd1_inherit_fig_defeatPolymorphism"> <title><quote>Defeating</quote> polymorphism</title> @@ -1193,9 +1195,10 @@ public class Rectangle } static void print(final Shape[] shapes) { for (final Shape s : shapes) { - if (s instanceof Rectangle) { + if (s <link xlink:href="https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.20.2">instanceof</link> Rectangle) { System.out.println("Type Rectangle"); - } else if (s instanceof Circle) { + } else if (s <link + xlink:href="https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.20.2">instanceof</link> Circle) { System.out.println("Type Circle"); } } @@ -1276,7 +1279,8 @@ Type Rectangle</screen></td> <programlisting language="java">public class Rectangle extends Shape { @Override public boolean equals(Object o) { - if (o instanceof Rectangle){ + if (o <link + xlink:href="https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.20.2">instanceof</link> Rectangle){ final Rectangle oRectangle = (Rectangle) o; return super.equalCenter(oRectangle) && Math.abs(oRectangle.width- width) + @@ -1287,7 +1291,9 @@ Type Rectangle</screen></td> ...</programlisting> <remark>if <code language="java">o == null</code> then <code - language="java">o instanceof Rectangle</code> evaluates to <code + language="java">o <link + xlink:href="https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.20.2">instanceof</link> + Rectangle</code> evaluates to <code language="java">false</code>.</remark> </figure> @@ -1297,7 +1303,8 @@ Type Rectangle</screen></td> <programlisting language="java">public class Circle extends Shape { @Override public boolean equals(final Object o) { - if (o instanceof Circle){ + if (o <link + xlink:href="https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.20.2">instanceof</link> Circle){ final Circle oCircle = (Circle) o; return super.equalCenter(o) && Math.abs(oCircle.radius - radius) < 1.E-15; diff --git a/Doc/Sda1/Ref/JpaIntro/P/StudyCourse_basic/src/main/java/de/hdm_stuttgart/mi/sda1/JpqlReadAllStudyCourseRecords.java b/Doc/Sda1/Ref/JpaIntro/P/StudyCourse_basic/src/main/java/de/hdm_stuttgart/mi/sda1/JpqlReadAllStudyCourseRecords.java new file mode 100644 index 0000000000000000000000000000000000000000..d0bc37cca10474968938e5a727594b614aa0c5c2 --- /dev/null +++ b/Doc/Sda1/Ref/JpaIntro/P/StudyCourse_basic/src/main/java/de/hdm_stuttgart/mi/sda1/JpqlReadAllStudyCourseRecords.java @@ -0,0 +1,39 @@ +package de.hdm_stuttgart.mi.sda1; + +import de.hdm_stuttgart.mi.sda1.model.StudyCourse; +import org.apache.log4j.LogManager; +import org.apache.log4j.Logger; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Persistence; +import javax.persistence.Query; + +/** + * Read a {@link StudyCourse} by its primary key value. + */ +public class JpqlReadAllStudyCourseRecords { + + static private final Logger log = LogManager.getLogger(JpqlReadAllStudyCourseRecords.class); + + static private final EntityManagerFactory factory = Persistence.createEntityManagerFactory( + "strategy_none"); + + static private final EntityManager entityManager = factory.createEntityManager(); + /** + * @param args unused + */ + public static void main( String[] args ) { + final Query queryRecords = entityManager.createQuery( + "SELECT S.fullName, S.shortName FROM StudyCourse AS S"); + + queryRecords.getResultList().stream(). + map(r -> { + final Object[] record = (Object[]) r; + return (String)record[0] + " (" + (String)record[1] + ")"; + }). + forEach(System.out::println); + + factory.close(); + } +} \ No newline at end of file diff --git a/Doc/Sda1/jpaintro.xml b/Doc/Sda1/jpaintro.xml index 576d46d4ebbc4c1033d7c618842f520c1d0a380a..c56cecc2da5ce27fc0f3795e6a3273854c0bd612 100644 --- a/Doc/Sda1/jpaintro.xml +++ b/Doc/Sda1/jpaintro.xml @@ -700,7 +700,10 @@ System.out.println("Read '" + studyCourse + "'"); <co <title>Retrieving all instances</title> <programlisting language="java">... -final Query query = entityManager.createQuery("SELECT s FROM StudyCourse s"); +final Query query = entityManager. + createQuery("SELECT S FROM StudyCourse S" <co + linkends="sda1_jpaintro_fig_readStudyCourseAll-1.2" + xml:id="sda1_jpaintro_fig_readStudyCourseAll-1.2-co"/>); final List<StudyCourse><co linkends="sda1_jpaintro_fig_readStudyCourseAll-1" @@ -708,29 +711,38 @@ final List<StudyCourse><co linkends="sda1_jpaintro_fig_readStudyCourseAll-2" xml:id="sda1_jpaintro_fig_readStudyCourseAll-2-co"/> query.getResultList(); -studyCourses.stream().map(s -> "Read '" + s + "'").forEach(System.out::println);</programlisting> - - <calloutlist> - <callout arearefs="sda1_jpaintro_fig_readStudyCourseAll-1-co" - xml:id="sda1_jpaintro_fig_readStudyCourseAll-1"> - <para>Notice: <classname - xlink:href="https://docs.oracle.com/javase/9/docs/api/java/util/List.html">List</classname> - in favour of <classname - xlink:href="https://docs.oracle.com/javase/9/docs/api/java/util/Set.html">Set</classname> - respecting database ordering.</para> - </callout> - - <callout arearefs="sda1_jpaintro_fig_readStudyCourseAll-2-co" - xml:id="sda1_jpaintro_fig_readStudyCourseAll-2"> - <para>Unchecked assignment <classname - xlink:href="https://docs.oracle.com/javase/9/docs/api/java/util/List.html">java.util.List</classname> - to <classname - xlink:href="https://docs.oracle.com/javase/9/docs/api/java/util/List.html">java.util.List</classname><<classname - xlink:href="https://gitlab.mi.hdm-stuttgart.de/goik/GoikLectures/blob/master/Doc/Sda1/Ref/JpaIntro/P/StudyCourse_basic/src/main/java/de/hdm_stuttgart/mi/sda1/model/StudyCourse.java">StudyCourse</classname>>.</para> - </callout> - </calloutlist> +studyCourses.stream().map(s -> "Read '" + s + "'"). + forEach(System.out::println);</programlisting> </figure> + <calloutlist> + <callout arearefs="sda1_jpaintro_fig_readStudyCourseAll-1.2-co" + xml:id="sda1_jpaintro_fig_readStudyCourseAll-1.2"> + <para>A <xref linkend="glo_JPQL"/> statement resembling <xref + linkend="glo_SQL"/> but actually retrieving <xref + linkend="glo_Java"/> objects rather than attribute value composed + database records.</para> + </callout> + + <callout arearefs="sda1_jpaintro_fig_readStudyCourseAll-1-co" + xml:id="sda1_jpaintro_fig_readStudyCourseAll-1"> + <para>Notice: <classname + xlink:href="https://docs.oracle.com/javase/9/docs/api/java/util/List.html">List</classname> + in favour of <classname + xlink:href="https://docs.oracle.com/javase/9/docs/api/java/util/Set.html">Set</classname> + respecting database ordering.</para> + </callout> + + <callout arearefs="sda1_jpaintro_fig_readStudyCourseAll-2-co" + xml:id="sda1_jpaintro_fig_readStudyCourseAll-2"> + <para>Unchecked assignment <classname + xlink:href="https://docs.oracle.com/javase/9/docs/api/java/util/List.html">java.util.List</classname> + to <classname + xlink:href="https://docs.oracle.com/javase/9/docs/api/java/util/List.html">java.util.List</classname><<classname + xlink:href="https://gitlab.mi.hdm-stuttgart.de/goik/GoikLectures/blob/master/Doc/Sda1/Ref/JpaIntro/P/StudyCourse_basic/src/main/java/de/hdm_stuttgart/mi/sda1/model/StudyCourse.java">StudyCourse</classname>>.</para> + </callout> + </calloutlist> + <figure xml:id="sda1_jpaintro_fig_readTypeViolate"> <title>Type conversion problems</title> @@ -750,7 +762,8 @@ try { <co linkends="sda1_jpaintro_fig_readTypeViolate-1" factory.close(); }</programlisting> - <screen>Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to de.hdm_stuttgart.mi.sda1.model.StudyCourse + <screen>Exception in thread "main" java.lang.ClassCastException: java.lang.String + cannot be cast to de.hdm_stuttgart.mi.sda1.model.StudyCourse ... at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418) at de.hdm_stuttgart.mi.sda1.JqlTypeViolation.main(JqlTypeViolation.java:29)</screen> @@ -792,7 +805,8 @@ studyCourseShortNames.stream(). xml:id="sda1_jpaintro_fig_readShortNames-3-co"/> + "'"). forEach(System.out::println);</programlisting> - <screen>Read 'CSM'</screen> + <screen>Read 'CSM' +...</screen> </figure> <calloutlist> @@ -865,12 +879,12 @@ tx.commit(); <co linkends="sda1_jpaintro_fig_updateStudyCourse-3" <td valign="top"><screen>MariaDB [hdm]> select * from StudyCourse; -+-----------+----------------------+ -| shortName | fullName | -+-----------+----------------------+ -| CSM | Computerwissenschaft | -| | und Medien | -+-----------+----------------------+</screen></td> ++---------+---------------------+ +|shortName| fullName | ++---------+---------------------+ +| CSM | Computerwissenschaft| +| | und Medien | ++---------+---------------------+</screen></td> </tr> </informaltable> </figure> @@ -904,10 +918,10 @@ tx.commit(); <co linkends="sda1_jpaintro_fig_updateStudyCourse-3" <title>Populating the database</title> <programlisting language="java">tx.begin(); - entityManager.persist(new StudyCourse("CSM", "Computer Science and Media")); - entityManager.persist(new StudyCourse("MMB", "Mobile Media")); - entityManager.persist(new StudyCourse("CRB", "Cross Media Journalism")); - entityManager.persist(new StudyCourse("IDB", "Information Design")); + entityManager.persist(new StudyCourse("CSM","Computer Science and Media")); + entityManager.persist(new StudyCourse("MMB","Mobile Media")); + entityManager.persist(new StudyCourse("CRB","Cross Media Journalism")); + entityManager.persist(new StudyCourse("IDB","Information Design")); tx.commit();</programlisting> </figure> @@ -938,8 +952,8 @@ entityManager.createQuery( <glossterm><xref linkend="glo_JPQL"/>:</glossterm> <glossdef> - <programlisting language="none">entityManager.createQuery("<emphasis - role="red">SELECT S FROM StudyCourse AS S WHERE S.shortName like 'C%'</emphasis>")</programlisting> + <programlisting language="none">entityManager.createQuery( + "<emphasis role="red">SELECT S FROM StudyCourse AS S WHERE S.shortName like 'C%'</emphasis>") </programlisting> </glossdef> </glossentry> @@ -952,8 +966,8 @@ entityManager.createQuery( <programlisting language="none">criteria.select(<emphasis role="red">studyCourseRoot</emphasis>); criteria.where( builder.<emphasis role="red">like</emphasis>( <emphasis - role="red">studyCourseRootRoot</emphasis>.get(<emphasis - role="red">StudyCourse_.shortName</emphasis>), "<emphasis + role="red">studyCourseRootRoot</emphasis>. + get(<emphasis role="red">StudyCourse_.shortName</emphasis>), "<emphasis role="red">C%</emphasis>" ) );</programlisting> </glossdef> </glossentry> @@ -1001,6 +1015,82 @@ query.setParameter("pattern", "<emphasis role="red">C%</emphasis>");</programlis from StudyCourse studycours0_ where studycours0_.shortName like <emphasis role="red">?</emphasis></programlisting> </figure> + + <figure xml:id="sda1_jpaintro_fig_jpqlRecordRetrieval"> + <title><xref linkend="glo_JPQL"/> record retrieval</title> + + <programlisting language="none">final Query queryRecords = entityManager.createQuery( + "SELECT S.<emphasis role="red">fullName</emphasis>, S.<emphasis role="red">shortName</emphasis> FROM StudyCourse AS S" <co + linkends="sda1_jpaintro_fig_jpqlRecordRetrieval-1" + xml:id="sda1_jpaintro_fig_jpqlRecordRetrieval-1-co"/>); +queryRecords.getResultList().stream(). + map(r -> { + final Object[] record = (Object[]) r; <co + linkends="sda1_jpaintro_fig_jpqlRecordRetrieval-2" + xml:id="sda1_jpaintro_fig_jpqlRecordRetrieval-2-co"/> + return (String)<emphasis role="red">record[0]</emphasis> + " (" + (String)<emphasis + role="red">record[1]</emphasis> + ")" <co + linkends="sda1_jpaintro_fig_jpqlRecordRetrieval-3" + xml:id="sda1_jpaintro_fig_jpqlRecordRetrieval-3-co"/>; + }).forEach(System.out::println)<co + linkends="sda1_jpaintro_fig_jpqlRecordRetrieval-4" + xml:id="sda1_jpaintro_fig_jpqlRecordRetrieval-4-co"/> ;</programlisting> + + <screen><emphasis role="red">Computer Science and Media</emphasis> (<emphasis + role="red">CSM</emphasis>) ...</screen> + </figure> + + <calloutlist> + <callout arearefs="sda1_jpaintro_fig_jpqlRecordRetrieval-1-co" + xml:id="sda1_jpaintro_fig_jpqlRecordRetrieval-1"> + <para>Retrieving two attribute values <emphasis + role="red">fullName</emphasis> and <emphasis + role="red">shortName</emphasis> from + <classname>StudyCourse</classname> records.</para> + + <note> + <para>Notice the ordering: <emphasis role="red">fullName</emphasis> + appears at first and <emphasis role="red">shortName</emphasis> at + second position.</para> + </note> + </callout> + + <callout arearefs="sda1_jpaintro_fig_jpqlRecordRetrieval-2-co" + xml:id="sda1_jpaintro_fig_jpqlRecordRetrieval-2"> + <para>Compile time prior knowledge: <xref linkend="glo_JPA"/> wraps + each database record into an <classname>Object[]</classname> array + typically (albeit in the current example) containing heterogeneous + instance references corresponding to database types being + involved.</para> + + <para>The array's size equals the number of database attributes being + requested being 2 in the given example. <emphasis + role="red">fullName</emphasis> and <emphasis + role="red">shortName</emphasis> record values appear at array index + positions 0 and 1 respectively.</para> + + <note> + <para>As with plain <xref linkend="glo_JDBC"/> you are on your own + handling types being involved accordingly. Obviously there is no + compile time type checking whatsoever. <code language="java" + xlink:href="https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.20.2">instanceof</code> + may save you from troubles.</para> + </note> + </callout> + + <callout arearefs="sda1_jpaintro_fig_jpqlRecordRetrieval-3-co" + xml:id="sda1_jpaintro_fig_jpqlRecordRetrieval-3"> + <para>Digging into array values: Since both <emphasis + role="red">fullName</emphasis> and <emphasis + role="red">shortName</emphasis> are strings identical casts are being + required.</para> + </callout> + + <callout arearefs="sda1_jpaintro_fig_jpqlRecordRetrieval-4-co" + xml:id="sda1_jpaintro_fig_jpqlRecordRetrieval-4"> + <para>Print values.</para> + </callout> + </calloutlist> </section> <section xml:id="sda1_jpa_sect_criteriaQuery"> @@ -1021,15 +1111,18 @@ where studycours0_.shortName like <emphasis role="red">?</emphasis></programlis <figure xml:id="sda1_jpaintro_fig_criteriaLike"> <title>Criteria query</title> - <programlisting language="none">final CriteriaQuery<StudyCourse> criteria = builder.createQuery( StudyCourse.class ); -final Root<StudyCourse> studyCourseRoot = criteria.from(<emphasis - role="red">StudyCourse.class</emphasis>); + <programlisting language="none">final CriteriaQuery<StudyCourse> criteria = builder. + createQuery( StudyCourse.class ); +final Root<StudyCourse> studyCourseRoot = + criteria.from(<emphasis role="red">StudyCourse.class</emphasis>); criteria.select( studyCourseRoot ); -criteria.where( builder.like( studyCourseRoot.get(StudyCourse_.shortName), "<emphasis - role="red">C%</emphasis>" ) ); -final List<StudyCourse> studyCourses = entityManager.createQuery( criteria ).getResultList(); +criteria.where( builder.like( studyCourseRoot. + get(StudyCourse_.shortName), "<emphasis role="red">C%</emphasis>" ) ); +final List<StudyCourse> studyCourses = entityManager. + createQuery( criteria ).getResultList(); -studyCourses.stream().map(s -> "Read '" + s + "'").forEach(System.out::println);</programlisting> +studyCourses.stream().map(s -> "Read '" + s + "'"). + forEach(System.out::println);</programlisting> <para>What about <xref linkend="glo_SQL"/> injection?</para> </figure> @@ -1081,14 +1174,17 @@ where studycours0_.shortName like <emphasis role="red">?</emphasis></programlist <tr> <td valign="top"><programlisting language="java">new JPAQuery(entityManager). from(qStudyCourse). - where(qStudyCourse.shortName.like("C%")). + where(qStudyCourse.shortName.like("C%")). list(qStudyCourse). stream(). - map(s -> "Like C%: Read '" + s + "'"). + map(s -> "Read '" + s + "'"). forEach(System.out::println);</programlisting></td> - <td valign="top"><screen>Like C%: Read 'Cross Media Journalism(CRB)' -Like C%: Read 'Computer Science and Media(CSM)' </screen></td> + <td valign="top"><screen>Read 'Cross Media + Journalism(CRB)' + +Read 'Computer Science + and Media(CSM)' </screen></td> </tr> </informaltable> </figure>