From b336564ee2a05d85acdfa994558df2ec8df2adef Mon Sep 17 00:00:00 2001 From: Martin Goik <goik@hdm-stuttgart.de> Date: Tue, 5 Dec 2017 12:32:55 +0100 Subject: [PATCH] Text to slides --- Doc/Common/snippets.xml | 12 + Doc/Sda1/jdbc.xml | 352 +++++++++++------- P/Sda1/Lectures/Surrogate/.gitignore | 4 + P/Sda1/Lectures/Surrogate/Data/lectures.xml | 26 ++ P/Sda1/Lectures/Surrogate/Data/university.xsd | 72 ++++ P/Sda1/Lectures/Surrogate/pom.xml | 91 +++++ .../java/de/hdm_stuttgart/mi/sda1/App.java | 29 ++ .../de/hdm_stuttgart/mi/sda1/ReadXmlData.java | 7 + .../mi/sda1/WriteRelationalData.java | 58 +++ .../src/main/resources/Data/testdata.sql | 5 + .../main/resources/Data/universityData.sql | 9 + .../main/resources/Data/universitySchema.sql | 20 + .../Surrogate/src/main/resources/log4j2.xml | 21 ++ .../hdm_stuttgart/mi/sda1/DatabaseTest.java | 107 ++++++ 14 files changed, 677 insertions(+), 136 deletions(-) create mode 100644 P/Sda1/Lectures/Surrogate/.gitignore create mode 100644 P/Sda1/Lectures/Surrogate/Data/lectures.xml create mode 100644 P/Sda1/Lectures/Surrogate/Data/university.xsd create mode 100644 P/Sda1/Lectures/Surrogate/pom.xml create mode 100644 P/Sda1/Lectures/Surrogate/src/main/java/de/hdm_stuttgart/mi/sda1/App.java create mode 100644 P/Sda1/Lectures/Surrogate/src/main/java/de/hdm_stuttgart/mi/sda1/ReadXmlData.java create mode 100644 P/Sda1/Lectures/Surrogate/src/main/java/de/hdm_stuttgart/mi/sda1/WriteRelationalData.java create mode 100644 P/Sda1/Lectures/Surrogate/src/main/resources/Data/testdata.sql create mode 100644 P/Sda1/Lectures/Surrogate/src/main/resources/Data/universityData.sql create mode 100644 P/Sda1/Lectures/Surrogate/src/main/resources/Data/universitySchema.sql create mode 100644 P/Sda1/Lectures/Surrogate/src/main/resources/log4j2.xml create mode 100644 P/Sda1/Lectures/Surrogate/src/test/java/de/hdm_stuttgart/mi/sda1/DatabaseTest.java diff --git a/Doc/Common/snippets.xml b/Doc/Common/snippets.xml index 905fd413a..980f4204e 100644 --- a/Doc/Common/snippets.xml +++ b/Doc/Common/snippets.xml @@ -17,4 +17,16 @@ <td valign="top"/> </tr> </informaltable> + + <qandaset defaultlabel="qanda" xml:id="qanda_"> + <title>X</title> + + <qandadiv> + <qandaentry> + <question> + <para/> + </question> + </qandaentry> + </qandadiv> + </qandaset> </chapter> diff --git a/Doc/Sda1/jdbc.xml b/Doc/Sda1/jdbc.xml index 969160efa..a61a0b18e 100644 --- a/Doc/Sda1/jdbc.xml +++ b/Doc/Sda1/jdbc.xml @@ -17,15 +17,22 @@ <itemizedlist> <listitem> <para><xref linkend="glo_RDBMS"/> schema and <xref - linkend="glo_Sql_DDL"/>.</para> + linkend="glo_Sql_DDL"/>:</para> + + <para><code>PRIMARY KEY</code>, <code>UNIQUE</code>, <code>FOREIGN + KEY</code>, <code>NOT NULL</code>, datatypes.</para> </listitem> <listitem> - <para><xref linkend="glo_SQL"/>, <xref linkend="glo_Sql_DML"/>.</para> + <para><xref linkend="glo_SQL"/>, <xref linkend="glo_Sql_DML"/>:</para> + + <para>Predicate based queries, joins.</para> </listitem> <listitem> - <para>Transactions, <xref linkend="glo_ACID"/> principle</para> + <para>Transactions, <xref linkend="glo_ACID"/> principle:</para> + + <para>Isolation level 1 - 4.</para> </listitem> </itemizedlist> </figure> @@ -67,12 +74,8 @@ User u = new User("Joe Bix", "bix");</programlisting> INSERT INTO User VALUES('Joe Bix', 'bix');</programlisting> </figure> - <para>A <xref linkend="glo_Java"/> application may create transient - instances of class <code>User</code> persisting these to a - database:</para> - <figure xml:id="processObjPersist"> - <title>Persistence across system boundaries</title> + <title>Persisting transient <code>User</code> instances</title> <mediaobject> <imageobject> @@ -115,8 +118,7 @@ INSERT INTO User VALUES('Joe Bix', 'bix');</programlisting> </section> <section xml:id="jdbcIntro"> - <title>Introduction to <trademark - xlink:href="https://en.wikipedia.org/wiki/Java_Database_Connectivity">JDBC</trademark></title> + <title>Introduction to <xref linkend="glo_JDBC"/></title> <section xml:id="jdbcWrite"> <title>Write access, principles</title> @@ -253,20 +255,24 @@ INSERT INTO User VALUES('Joe Bix', 'bix');</programlisting> </mediaobject> </figure> - <para>In fact this <trademark - xlink:href="https://en.wikipedia.org/wiki/Java_Database_Connectivity">JDBC</trademark> - URL example closely resembles other types of URL strings as being - defined in <uri - xlink:href="https://www.ietf.org/rfc/rfc2396.txt">http://www.ietf.org/rfc/rfc2396.txt</uri>. - Look for <code>opaque_part</code> to understand the second - <quote>:</quote> in the protocol definition part of a <trademark - xlink:href="https://en.wikipedia.org/wiki/Java_Database_Connectivity">JDBC</trademark> - URL. Common example for <abbrev - xlink:href="https://www.ietf.org/rfc/rfc1738.txt">URL</abbrev>s - are:</para> + <figure xml:id="sda1_fig_jdbc_UrlRfc"> + <title><xref linkend="glo_IETF"/> Uniform Resource Identifier</title> + + <para><uri + xlink:href="https://www.ietf.org/rfc/rfc2396.txt">https://www.ietf.org/rfc/rfc2396.txt</uri>:</para> + + <programlisting language="bnf">absoluteURI = scheme ":" ( hier_part | opaque_part ) + +hier_part = ( net_path | abs_path ) [ "?" query ] + +net_path = "//" authority [ abs_path ] + +abs_path = "/" path_segments +...</programlisting> + </figure> <figure xml:id="sda1_jdbc_fig_protocolExamples"> - <title>protocol URL examples</title> + <title><xref linkend="glo_URL"/> examples</title> <itemizedlist> <listitem> @@ -319,9 +325,9 @@ INSERT INTO User VALUES('Joe Bix', 'bix');</programlisting> <title>No standard port assignments ...</title> <informaltable border="1"> - <colgroup width="16%"/> + <colgroup width="35%"/> - <colgroup width="84%"/> + <colgroup width="65%"/> <tr> <td valign="top"><glosslist> @@ -334,7 +340,7 @@ INSERT INTO User VALUES('Joe Bix', 'bix');</programlisting> </glossentry> <glossentry> - <glossterm>IBM DB2</glossterm> + <glossterm>IBM DB2:</glossterm> <glossdef> <para>50000</para> @@ -342,7 +348,7 @@ INSERT INTO User VALUES('Joe Bix', 'bix');</programlisting> </glossentry> <glossentry> - <glossterm>Oracle</glossterm> + <glossterm>Oracle:</glossterm> <glossdef> <para>1521</para> @@ -383,7 +389,7 @@ mysql-proxy 6446/udp</screen> xlink:href="https://en.wikipedia.org/wiki/Java_Database_Connectivity">JDBC</trademark> based applications follows a simple scheme:</para> - <figure xml:id="jdbcArchitecture"> + <figure xml:id="sda1_fig_jdbcArchitecture"> <title><xref linkend="glo_JDBC"/> architecture</title> <mediaobject> @@ -400,7 +406,9 @@ mysql-proxy 6446/udp</screen> instances are being created from this central and unique object.</para> <figure xml:id="sda1_jdbc_fig_jdbcBootstrap"> - <title>DriverManager: Bootstrapping connections</title> + <title><classname + xlink:href="https://docs.oracle.com/javase/9/docs/api/java/sql/DriverManager.html">DriverManager</classname>: + Bootstrapping connections</title> <itemizedlist> <listitem> @@ -457,8 +465,8 @@ mysql-proxy 6446/udp</screen> rough description of these three interfaces' tasks and responsibilities:</para> - <figure xml:id="sda1_jdbc_fig_importantInterfaces"> - <title>Prominent <xref linkend="glo_JDBC"/> interfaces</title> + <figure xml:id="sda1_jdbc_fig_ConnectionInterface"> + <title><classname>Connection</classname> interface</title> <glosslist> <glossentry> @@ -466,13 +474,40 @@ mysql-proxy 6446/udp</screen> xlink:href="https://docs.oracle.com/javase/9/docs/api/java/sql/Connection.html">java.sql.Connection</classname></glossterm> <glossdef> - <para>Holding a permanent connection to a database server. Both - client and server can contact each other. The database server - may for example terminate a transaction if problems like - deadlocks occur.</para> + <itemizedlist> + <listitem> + <para>Holding a permanent database server connection + .</para> + </listitem> + + <listitem> + <para>Stateful protocol.</para> + </listitem> + + <listitem> + <para>Per connection properties: <link + xlink:href="https://docs.oracle.com/javase/9/docs/api/java/sql/Connection.html#setTransactionIsolation-int-">Isolation + level</link>, <link + xlink:href="https://docs.oracle.com/javase/9/docs/api/java/sql/Connection.html#setAutoCommit-boolean-">auto + commit</link>,...</para> + </listitem> + + <listitem> + <para><methodname + xlink:href="https://docs.oracle.com/javase/9/docs/api/java/sql/Connection.html#rollback--">rollback()</methodname> + / <methodname + xlink:href="https://docs.oracle.com/javase/9/docs/api/java/sql/Connection.html#commit--">commit()</methodname>.</para> + </listitem> + </itemizedlist> </glossdef> </glossentry> + </glosslist> + </figure> + + <figure xml:id="sda1_jdbc_fig_StatementInterface"> + <title><classname>Statement</classname> interface</title> + <glosslist> <glossentry> <glossterm><classname xlink:href="https://docs.oracle.com/javase/9/docs/api/java/sql/Statement.html">java.sql.Statement</classname></glossterm> @@ -482,23 +517,23 @@ mysql-proxy 6446/udp</screen> <glosslist> <glossentry> - <glossterm><code>INSERT</code>, <code>UPDATE</code>, - <code>DELETE</code></glossterm> + <glossterm><code + xlink:href="https://docs.oracle.com/javase/9/docs/api/java/sql/Statement.html#executeUpdate-java.lang.String-">executeUpdate()</code></glossterm> <glossdef> - <para>Modify server records, client gets integer return - codes.</para> + <para><code>INSERT</code>, <code>UPDATE</code>, + <code>DELETE</code>: Integer return code</para> </glossdef> </glossentry> <glossentry> - <glossterm><code>SELECT</code></glossterm> + <glossterm><code + xlink:href="https://docs.oracle.com/javase/9/docs/api/java/sql/Statement.html#executeQuery-java.lang.String-">executeQuery()</code></glossterm> <glossdef> - <para>Reading server records, providing <classname - xlink:href="https://docs.oracle.com/javase/9/docs/api/java/sql/ResultSet.html">java.sql.ResultSet</classname> - client side container, see <xref - linkend="jdbcRead"/>.</para> + <para><code>SELECT</code>: Returning <classname + xlink:href="https://docs.oracle.com/javase/9/docs/api/java/sql/ResultSet.html">java.sql.ResultSet</classname>, + see <xref linkend="jdbcRead"/>.</para> </glossdef> </glossentry> </glosslist> @@ -507,65 +542,95 @@ mysql-proxy 6446/udp</screen> </glosslist> </figure> - <para>We shed some light on the relationship between these important - <trademark - xlink:href="http://www.oracle.com/technetwork/java/javase/jdbc">JDBC</trademark> - components and their respective creation:<figure - xml:id="jdbcObjectCreation"> - <title>Important <trademark - xlink:href="http://www.oracle.com/technetwork/java/javase/jdbc">JDBC</trademark> - instances and relationships.</title> + <figure xml:id="jdbcObjectCreation"> + <title><trademark + xlink:href="http://www.oracle.com/technetwork/java/javase/jdbc">JDBC</trademark> + instances and relationships.</title> - <mediaobject> - <imageobject> - <imagedata fileref="Ref/Fig/jdbcObjectRelation.fig"/> - </imageobject> - </mediaobject> - </figure></para> + <mediaobject> + <imageobject> + <imagedata fileref="Ref/Fig/jdbcObjectRelation.fig"/> + </imageobject> + </mediaobject> + </figure> </section> <section xml:id="writeAccessCoding"> <title>Write access, coding!</title> + <para><xref linkend="glo_JDBC"/> applications require a per project + driver configuration:</para> + + <figure xml:id="sda1_fig_configureMysqlMaven"> + <title><filename>pom.xml</filename> <xref linkend="glo_Maven"/> <xref + linkend="glo_Soft_Mysql"/> driver dependency</title> + + <programlisting language="xml">... +<dependency> + <groupId>mysql</groupId> + <artifactId>mysql-connector-java</artifactId> + <version>5.1.45</version> + <scope><emphasis role="red">runtime</emphasis></scope> +</dependency> ...</programlisting> + </figure> + + <qandaset defaultlabel="qanda" xml:id="sda1_qanda_whyScopeRuntime"> + <title>Why <tag class="starttag">scope</tag><code>runtime</code><tag + class="endtag">scope</tag>?</title> + + <qandadiv> + <qandaentry> + <question> + <para>Why is the <xref linkend="glo_JDBC"/> <link + linkend="sda1_fig_configureMysqlMaven">driver dependency</link> + not being required at compile time?</para> + </question> + + <answer> + <para>According to <xref linkend="sda1_fig_jdbcArchitecture"/> a + <xref linkend="glo_JDBC"/> based application requires just + interfaces rather than classes at compile time. The actual + instances of <classname + xlink:href="https://docs.oracle.com/javase/9/docs/api/java/sql/Connection.html">java.sql.Connection</classname>, + <classname + xlink:href="https://docs.oracle.com/javase/9/docs/api/java/sql/Statement.html">java.sql.Statement</classname> + and so on will be created during the bootstrap process starting + from <classname + xlink:href="https://docs.oracle.com/javase/9/docs/api/java/sql/DriverManager.html">java.sql.DriverManager</classname>.</para> + </answer> + </qandaentry> + </qandadiv> + </qandaset> + <para>So how does it actually work with respect to coding? You may want to read <xref linkend="toolingConfigJdbc"/> before starting your - exercises. We first prepare a database table using Eclipse's database - tools:</para> + exercises. We first prepare a database table:</para> <figure xml:id="figSchemaPerson"> - <title>A relation <code>Person</code> containing names and email - addresses</title> + <title><code>Person</code> table </title> <programlisting language="sql"><emphasis role="strong">CREATE</emphasis> <emphasis role="strong">TABLE</emphasis> Person ( name CHAR(20) - ,email CHAR(20) <emphasis>UNIQUE</emphasis>)</programlisting> - </figure> - - <figure xml:id="sda1_fig_configureMysqlMaven"> - <title><xref linkend="glo_Maven"/> <xref linkend="glo_Soft_Mysql"/> - driver dependency</title> - - <programlisting language="xml"><dependency> - <groupId>mysql</groupId> - <artifactId>mysql-connector-java</artifactId> - <version>5.1.41</version> -</dependency></programlisting> + ,email CHAR(20) <emphasis>UNIQUE</emphasis> +)</programlisting> </figure> <figure xml:id="sda1_fig_addPersonDataset"> <title>Objective: insert person record</title> + <para><xref linkend="glo_Java"/> application executing:</para> + <programlisting language="xml">INSERT INTO Person VALUES('Jim', 'jim@foo.org')</programlisting> <itemizedlist> <listitem> - <para>No database read required (No - <classname>java.sql.ResultSet</classname>).</para> + <para>No database read required (No <classname + xlink:href="https://docs.oracle.com/javase/9/docs/api/java/sql/ResultSet.html">java.sql.ResultSet</classname>).</para> </listitem> <listitem> - <para>Success / failure related return parameter.</para> + <para>Success / failure related database return parameter.</para> </listitem> </itemizedlist> </figure> @@ -577,34 +642,51 @@ mysql-proxy 6446/udp</screen> <programlisting language="java">// <link xlink:href="https://gitlab.mi.hdm-stuttgart.de/goik/GoikLectures/blob/master/ws/eclipse/Jdbc/src/main/java/sda/jdbc/intro/SimpleInsert.java#L22">Step 1: Open connection to database server</link> -final Connection conn = DriverManager.getConnection ( +final Connection conn = DriverManager.<link + xlink:href="https://docs.oracle.com/javase/9/docs/api/java/sql/DriverManager.html#getConnection-java.lang.String-">getConnection</link> ( "jdbc:mysql://localhost:3306/hdm", "hdmuser", // Username - "XYZ"); // Password + "XYZ"); // Password + // Step 2: Create a Statement instance -final Statement stmt = conn.createStatement(); +final Statement stmt = conn.<link + xlink:href="https://docs.oracle.com/javase/9/docs/api/java/sql/Connection.html#createStatement--">createStatement()</link>; + // Step 3: Execute the desired INSERT -final int updateCount = stmt.executeUpdate( - "INSERT INTO Person VALUES('Jim', 'jim@foo.org')"); +final int updateCount = stmt.<link + xlink:href="https://docs.oracle.com/javase/9/docs/api/java/sql/Statement.html#executeUpdate-java.lang.String-">executeUpdate</link>( + "INSERT INTO Person VALUES('Jim', 'jim@foo.org')"); + // Step 4: Give feedback to the end user -System.out.println("Successfully inserted " + updateCount + " dataset(s)"); -}</programlisting> +System.out.println("Successfully inserted " + updateCount + " dataset(s)");</programlisting> </figure> - <remark>Having configured <xref linkend="glo_Soft_IntellijIDEA"/> you - may wonder why this does not provide a corresponding <xref - linkend="glo_JDBC"/> driver to any <xref linkend="glo_Java"/> or <xref - linkend="glo_Maven"/> based project in your workspace. This assumption - is wrong: Projects in <xref linkend="glo_Soft_IntellijIDEA"/> and the - <xref linkend="glo_Soft_IntellijIDEA"/> <xref linkend="glo_SQL"/> editor - are two completely distinct matters altogether.</remark> - - <para>Execution works as expected:</para> - <figure xml:id="sda1_figJ_dbcSimpleWriteResult"> <title>Result</title> + <para>Execution yields:</para> + <screen>Successfully inserted 1 dataset(s)</screen> + + <note> + <para>The database server <link + xlink:href="https://docs.oracle.com/javase/9/docs/api/java/sql/Statement.html#executeUpdate-java.lang.String-">returns</link> + the number of inserted datasets.</para> + </note> + </figure> + + <figure xml:id="sda1_fig_jdbcTwiceConfig"> + <title>Two <xref linkend="glo_JDBC"/> configurations.</title> + + <orderedlist> + <listitem> + <para><xref linkend="glo_IDE"/> level.</para> + </listitem> + + <listitem> + <para>Project level (<xref linkend="glo_Maven"/>).</para> + </listitem> + </orderedlist> </figure> <qandaset defaultlabel="qanda" xml:id="quandaentry_DupInsert"> @@ -642,31 +724,25 @@ System.out.println("Successfully inserted " + updateCount + " dataset(s)"); </qandadiv> </qandaset> - <note> - <para>It is worth mentioning that the <productname - xlink:href="https://www.mysql.com">Mysql</productname> and other <xref - linkend="glo_JDBC"/> driver implementations do not have to be present - at compile time. <trademark - xlink:href="https://en.wikipedia.org/wiki/Java_Database_Connectivity">JDBC</trademark> - defines interfaces in favour of (concrete) classes. The latter are - only required at runtime.</para> - </note> + <qandaset defaultlabel="qanda" xml:id="quandaentry_insertInteractive"> + <title>Interactive inserts</title> + + <qandadiv> + <qandaentry> + <question> + <para>Extend the previous example by adding support for + interactive insert of person data. <classname + xlink:href="https://docs.oracle.com/javase/9/docs/api/java/util/Scanner.html">java.util.Scanner</classname> + is your friend.</para> + </question> + </qandaentry> + </qandadiv> + </qandaset> <para>We now discuss some important <trademark xlink:href="https://en.wikipedia.org/wiki/Java_Database_Connectivity">JDBC</trademark> interface methods:</para> - <figure xml:id="sda1_fig_jdbcDriverRuntime"> - <title>Runtime only</title> - - <programlisting language="xml"><dependency> - <groupId>mysql</groupId> - <artifactId>mysql-connector-java</artifactId> - <version>6.0.2</version> - <scope>runtime</scope> -</dependency></programlisting> - </figure> - <glosslist> <glossentry> <glossterm><classname>java.sql.Connection</classname></glossterm> @@ -924,14 +1000,13 @@ Statement createStatement(int resultSetType, ... }</programlisting> - <para>If a programmer uses <trademark + <para>Using <trademark xlink:href="https://en.wikipedia.org/wiki/Java_Database_Connectivity">JDBC</trademark> - interfaces rather than a specific vendor's classes it is much - easier to make the resulting application work with databases - from other vendors. This requires a database vendor's - implementation not to be exposed to our own <xref - linkend="glo_Java"/> code but shielded by a neutral set of - interfaces.</para> + interfaces rather than vendor specific classes allows for + decoupling an application from a specific database platform. It + requires a database vendor's implementation not to be exposed to + our own <xref linkend="glo_Java"/> code but shielded it by a + neutral set of interfaces.</para> <para>Regarding the special role of <classname xlink:href="https://docs.oracle.com/javase/8/docs/api/java/sql/DriverManager.html">DriverManager</classname> @@ -1094,8 +1169,8 @@ public someClass { files:</para> <figure xml:id="propertyExternalization"> - <title>Externalize a single string <code>"User name"</code> to a - separate file <filename>message.properties</filename>.</title> + <title>String externalization to + <filename>message.properties</filename>.</title> <mediaobject> <imageobject> @@ -1625,8 +1700,8 @@ public class SimpleInsert { and <quote>connected</quote>:</para> <figure xml:id="figPersistenceHandlerStates"> - <title>Possible states and transitions for instances of - <code>PersistenceHandler</code>.</title> + <title><classname>PersistenceHandler</classname> state + transitions.</title> <mediaobject> <imageobject> @@ -2060,8 +2135,7 @@ public class ViewMockup implements PersistView { breach:</para> <figure xml:id="figHeartlandSecurityBreach"> - <title>Summary about possible SQL injection impact based on the - Heartland security breach</title> + <title>SQL injection impact</title> <mediaobject> <imageobject> @@ -2090,7 +2164,7 @@ public class ViewMockup implements PersistView { end user input:</para> <figure xml:id="figSqlInject"> - <title>SQL injection triggered by ordinary user input.</title> + <title>SQL injection principle</title> <mediaobject> <imageobject> @@ -2102,16 +2176,22 @@ public class ViewMockup implements PersistView { <para>And a nice explanation from <link xlink:href="???">http://xkcd.com/327</link>:</para> - <mediaobject> - <imageobject> - <imagedata fileref="Ref/Fig/exploits_of_a_mom.png"/> - </imageobject> - </mediaobject> + <figure xml:id="sda1_fig_littleBobbyTables"> + <title>Trouble at school ...</title> + + <mediaobject> + <imageobject> + <imagedata fileref="Ref/Fig/exploits_of_a_mom.png"/> + </imageobject> + </mediaobject> + </figure> + + <figure xml:id="sda1_fig_sqlInjectLessonsLearned"> + <title>Lessons learned?</title> - <para>Lessons learned? Current achievements <link - xlink:href="https://cwe.mitre.org/top25/#Listing">continue</link> to - be <link - xlink:href="https://www.cvedetails.com/vulnerability-search.php?f=1&vendor=&product=&cveid=&cweid=&cvssscoremin=&cvssscoremax=&psy=&psm=&pey=&pem=&usy=&usm=&uey=&uem=&opsqli=1">questionable</link>.</para> + <para>Current achievements continue to be <link + xlink:href="https://www.cvedetails.com/vulnerability-search.php?f=1&vendor=&product=&cveid=&cweid=&cvssscoremin=&cvssscoremax=&psy=&psm=&pey=&pem=&usy=&usm=&uey=&uem=&opsqli=1">questionable</link>.</para> + </figure> <qandaset defaultlabel="qanda" xml:id="sqlInjectDropTable"> <title>Attack from the dark side</title> diff --git a/P/Sda1/Lectures/Surrogate/.gitignore b/P/Sda1/Lectures/Surrogate/.gitignore new file mode 100644 index 000000000..a1c3ab4d0 --- /dev/null +++ b/P/Sda1/Lectures/Surrogate/.gitignore @@ -0,0 +1,4 @@ +/target/ +/.settings/ +.classpath +.project diff --git a/P/Sda1/Lectures/Surrogate/Data/lectures.xml b/P/Sda1/Lectures/Surrogate/Data/lectures.xml new file mode 100644 index 000000000..a550da181 --- /dev/null +++ b/P/Sda1/Lectures/Surrogate/Data/lectures.xml @@ -0,0 +1,26 @@ +<data xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" +xsi:noNamespaceSchemaLocation="university.xsd"> + <lecturers> + <lecturer ident="goik" email="goik@hdm-stuttgart.de"> + <name>Martin Goik</name> + </lecturer> + <lecturer ident="hahn" > + <name>Jens Hahn</name> + </lecturer> + </lecturers> + + <courses> + <course number="113105" lecturer="goik"> + <title>Software Development 1</title> + <description>Introduction to Java</description> + </course> + + <course number="1131099" lecturer="hahn"> + <title>Mathematics</title> + </course> + + <course number="113305" lecturer="goik"> + <title>Structured data and applications</title> + </course> + </courses> +</data> \ No newline at end of file diff --git a/P/Sda1/Lectures/Surrogate/Data/university.xsd b/P/Sda1/Lectures/Surrogate/Data/university.xsd new file mode 100644 index 000000000..b9f436a02 --- /dev/null +++ b/P/Sda1/Lectures/Surrogate/Data/university.xsd @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" + xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning" vc:minVersion="1.1" > + + <xs:element name="data"> + <xs:complexType> + <xs:sequence> + <xs:element ref="lecturers"/> + <xs:element ref="courses"/> + </xs:sequence> + </xs:complexType> + + <xs:key name="uniqueLecturerId"> + <xs:selector xpath="lecturers/lecturer"/> + <xs:field xpath="@ident"/> + </xs:key> + + <xs:key name="uniqueCourseId"> + <xs:selector xpath="courses/course"/> + <xs:field xpath="@number"/> + </xs:key> + + <xs:keyref name="courseLecturere" refer="uniqueLecturerId"> + <xs:selector xpath="courses/course"/> + <xs:field xpath="@lecturer"/> + </xs:keyref> + + </xs:element> + + <xs:element name="lecturers"> + <xs:complexType> + <xs:sequence> + <xs:element ref="lecturer" minOccurs="0" maxOccurs="unbounded"/> + </xs:sequence> + </xs:complexType> + + </xs:element> + + <xs:element name="lecturer"> + <xs:complexType> + <xs:sequence> + <xs:element name="name"/> + </xs:sequence> + <xs:attribute name="ident" use="required" type="xs:token"/> + <xs:attribute name="email" use="optional"/> + </xs:complexType> + + </xs:element> + + <xs:element name="courses"> + <xs:complexType> + <xs:sequence> + <xs:element ref="course" minOccurs="0" maxOccurs="unbounded"/> + </xs:sequence> + </xs:complexType> + + </xs:element> + + <xs:element name="course"> + <xs:complexType> + <xs:sequence> + <xs:element name="title"/> + <xs:element name="description" minOccurs="0"/> + </xs:sequence> + <xs:attribute name="number" use="required" type="xs:int"/> + <xs:attribute name="lecturer" use="required" type="xs:token"/> + </xs:complexType> + + </xs:element> + + +</xs:schema> diff --git a/P/Sda1/Lectures/Surrogate/pom.xml b/P/Sda1/Lectures/Surrogate/pom.xml new file mode 100644 index 000000000..4feffb900 --- /dev/null +++ b/P/Sda1/Lectures/Surrogate/pom.xml @@ -0,0 +1,91 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <groupId>de.hdm_stuttgart.mi.sda1</groupId> + <artifactId>lectures_surrogate</artifactId> + <version>0.9</version> + <packaging>jar</packaging> + + <name>lectures_surrogate</name> + + <url>https://freedocs.mi.hdm-stuttgart.de/sd1SectToolsOfTheTrade2.html</url> + + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + </properties> + + <dependencies> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.12</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j-core</artifactId> + <version>2.9.1</version> + </dependency> + <dependency> + <groupId>mysql</groupId> + <artifactId>mysql-connector-java</artifactId> + <version>6.0.6</version> + <scope>runtime</scope> + </dependency> + <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc --> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-jdbc</artifactId> + <version>5.0.2.RELEASE</version> + </dependency> + + </dependencies> + + <build> + <plugins> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.7.0</version> + <configuration> + <source>1.8</source> + <target>1.8</target> + </configuration> + </plugin> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-javadoc-plugin</artifactId> + <version>2.10.4</version> + <configuration /> + </plugin> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-shade-plugin</artifactId> + <version>3.1.0</version> + <configuration> + <transformers> + <transformer + implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> + <manifestEntries> + <Main-Class>de.hdm_stuttgart.mi.sda1.App</Main-Class> + </manifestEntries> + </transformer> + </transformers> + </configuration> + <executions> + <execution> + <phase>package</phase> + <goals> + <goal>shade</goal> + </goals> + </execution> + </executions> + </plugin> + + </plugins> + </build> +</project> diff --git a/P/Sda1/Lectures/Surrogate/src/main/java/de/hdm_stuttgart/mi/sda1/App.java b/P/Sda1/Lectures/Surrogate/src/main/java/de/hdm_stuttgart/mi/sda1/App.java new file mode 100644 index 000000000..127c25b4b --- /dev/null +++ b/P/Sda1/Lectures/Surrogate/src/main/java/de/hdm_stuttgart/mi/sda1/App.java @@ -0,0 +1,29 @@ +package de.hdm_stuttgart.mi.sda1; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + + +/** + * A simple http://logging.apache.org/log4j/2.x demo, + * see file resources/log4j2.xml for configuration options + * and A1.log containing debugging output. + */ + +public class App { + private static Logger log = LogManager.getLogger(App.class); + + /** + * Your application's main entry point. + * + * @param args Yet unused + */ + public static void main( String[] args ) { + System.out.println( "Hello World!" ); + + log.debug("With respect to logging you may want to configure file "); + log.debug("'src/main/resources/log4j2.xml' to suit your needs."); + log.debug("This config file 'log4j2.xml' will result in 'A1.log'"); + log.debug("file containing logging output as well."); + } +} diff --git a/P/Sda1/Lectures/Surrogate/src/main/java/de/hdm_stuttgart/mi/sda1/ReadXmlData.java b/P/Sda1/Lectures/Surrogate/src/main/java/de/hdm_stuttgart/mi/sda1/ReadXmlData.java new file mode 100644 index 000000000..ca1cc1c67 --- /dev/null +++ b/P/Sda1/Lectures/Surrogate/src/main/java/de/hdm_stuttgart/mi/sda1/ReadXmlData.java @@ -0,0 +1,7 @@ +package de.hdm_stuttgart.mi.sda1; + +public class ReadXmlData { + + + +} diff --git a/P/Sda1/Lectures/Surrogate/src/main/java/de/hdm_stuttgart/mi/sda1/WriteRelationalData.java b/P/Sda1/Lectures/Surrogate/src/main/java/de/hdm_stuttgart/mi/sda1/WriteRelationalData.java new file mode 100644 index 000000000..5ab64fe18 --- /dev/null +++ b/P/Sda1/Lectures/Surrogate/src/main/java/de/hdm_stuttgart/mi/sda1/WriteRelationalData.java @@ -0,0 +1,58 @@ +package de.hdm_stuttgart.mi.sda1; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.sql.*; + +public class WriteRelationalData implements AutoCloseable { + + static final Logger log = LogManager.getLogger(WriteRelationalData.class); + + final Connection conn; + final PreparedStatement insertLecturer,insertCourse; + + public WriteRelationalData(final Connection conn) throws SQLException { + this.conn = conn; + insertLecturer = conn.prepareStatement( + "INSERT INTO Lecturer (ident, name, email) VALUES (?, ?, ?)", + Statement.RETURN_GENERATED_KEYS); + + insertCourse = conn.prepareStatement( + "INSERT INTO Course (number, lecturerer, title, description) VALUES (?, ?, ?, ?)", + Statement.RETURN_GENERATED_KEYS); + } + + @Override + public void close() throws Exception { + conn.close(); + } + + public long insertLecturer(final String ident, final String name, final String email) throws SQLException { + + insertLecturer.setString(1, ident); + insertLecturer.setString(2, name); + insertLecturer.setString(3, email); + + if (1 == insertLecturer.executeUpdate()) { + try (final ResultSet generatedKeys = insertLecturer.getGeneratedKeys()) { + if (generatedKeys.next()) { + return generatedKeys.getLong(1); + } else { + log.warn("Unable to retrieve auto generated keys for record '" + name + "': "); + } + } + } + return -1; + } + public int insertCourse(final int number, final long lecturer, final String title, final String description) + throws SQLException { + log.info("lecturer: " + lecturer); + insertCourse.setInt(1, number); + insertCourse.setLong(2, lecturer); + insertCourse.setString(3, title); + insertCourse.setString(4, description); + + return insertCourse.executeUpdate(); + } +} \ No newline at end of file diff --git a/P/Sda1/Lectures/Surrogate/src/main/resources/Data/testdata.sql b/P/Sda1/Lectures/Surrogate/src/main/resources/Data/testdata.sql new file mode 100644 index 000000000..722984d09 --- /dev/null +++ b/P/Sda1/Lectures/Surrogate/src/main/resources/Data/testdata.sql @@ -0,0 +1,5 @@ +SELECT * from Lecturer; +SELECT * from Course; + +SELECT * from Lecturer, Course +WHERE lecturerer = Lecturer.id; \ No newline at end of file diff --git a/P/Sda1/Lectures/Surrogate/src/main/resources/Data/universityData.sql b/P/Sda1/Lectures/Surrogate/src/main/resources/Data/universityData.sql new file mode 100644 index 000000000..1be3184cb --- /dev/null +++ b/P/Sda1/Lectures/Surrogate/src/main/resources/Data/universityData.sql @@ -0,0 +1,9 @@ +INSERT INTO Lecturer (ident, name, email) VALUES ('goik', 'Martin Goik', 'goik@hdm-stuttgart.de'); +INSERT INTO Lecturer (ident, name, email) VALUES ('hahn', 'Jens Hahn', NULL); + +INSERT INTO Course (number, title, description, lecturerer) +VALUES (113105, 'Software Development 1', 'Introduction to Java', 1); +INSERT INTO Course (number, title, lecturerer) +VALUES (113109, 'Mathematics', 2); +INSERT INTO Course (number, title, lecturerer) +VALUES (113305, 'Structured data and applications', 1); diff --git a/P/Sda1/Lectures/Surrogate/src/main/resources/Data/universitySchema.sql b/P/Sda1/Lectures/Surrogate/src/main/resources/Data/universitySchema.sql new file mode 100644 index 000000000..7b8bf401d --- /dev/null +++ b/P/Sda1/Lectures/Surrogate/src/main/resources/Data/universitySchema.sql @@ -0,0 +1,20 @@ +DROP TABLE IF EXISTS Course; +DROP TABLE IF EXISTS Lecturer; + +CREATE TABLE Lecturer ( + id INT AUTO_INCREMENT + ,PRIMARY KEY(id) + ,ident CHAR(20) NOT NULL UNIQUE + ,name VARCHAR(20) + ,email VARCHAR(40) +); + +CREATE TABLE Course ( + id INT NOT NULL AUTO_INCREMENT PRIMARY KEY + ,number INT NOT NULL UNIQUE + ,title VARCHAR(40) + ,description VARCHAR(255) NULL + ,lecturerer INT NOT NULL REFERENCES Lecturer +); + + diff --git a/P/Sda1/Lectures/Surrogate/src/main/resources/log4j2.xml b/P/Sda1/Lectures/Surrogate/src/main/resources/log4j2.xml new file mode 100644 index 000000000..eb20b442a --- /dev/null +++ b/P/Sda1/Lectures/Surrogate/src/main/resources/log4j2.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Configuration> + <Appenders> + <File name="A1" fileName="A1.log" append="false"> + <PatternLayout pattern="%t %-5p %c{2} - %m%n"/> + </File> + <Console name="STDOUT" target="SYSTEM_OUT"> + <PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/> + </Console> + </Appenders> + <Loggers> + + <!-- You my want to define class or package level per-logger rules --> + <Logger name="de.hdm_stuttgart.mi.sda1.App" level="debug"> + <AppenderRef ref="A1"/> + </Logger> + <Root level="info"> + <AppenderRef ref="STDOUT"/> + </Root> + </Loggers> +</Configuration> \ No newline at end of file diff --git a/P/Sda1/Lectures/Surrogate/src/test/java/de/hdm_stuttgart/mi/sda1/DatabaseTest.java b/P/Sda1/Lectures/Surrogate/src/test/java/de/hdm_stuttgart/mi/sda1/DatabaseTest.java new file mode 100644 index 000000000..08e74f6ee --- /dev/null +++ b/P/Sda1/Lectures/Surrogate/src/test/java/de/hdm_stuttgart/mi/sda1/DatabaseTest.java @@ -0,0 +1,107 @@ +package de.hdm_stuttgart.mi.sda1; + +import org.junit.*; +import org.junit.rules.ExpectedException; +import org.junit.runners.MethodSorters; +import org.springframework.core.io.ClassPathResource; +import org.springframework.jdbc.datasource.init.ScriptUtils; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.sql.SQLIntegrityConstraintViolationException; + +/** + * Testing SQL data insertion. + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class DatabaseTest { + + static Connection conn; + + static long goikId, hahnId; + + @BeforeClass + static public void initDatabase() throws SQLException { + conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/hdm", "hdmuser", "XYZ"); + ScriptUtils.executeSqlScript(conn, new ClassPathResource("Data/universitySchema.sql")); + } + + @AfterClass + static public void releaseDatabase() throws SQLException { + conn.close(); + } + + /** + * first lecturer record. + */ + @Test + public void testDatabase_010 () throws SQLException { + final WriteRelationalData write = new WriteRelationalData(conn); + goikId = write.insertLecturer("goik", "Martin Goik", "goik@hdm-stuttgart.de"); + Assert.assertTrue( 0 < goikId); + } + /** + * Testing duplicate insert. + */ + @Test(expected = SQLIntegrityConstraintViolationException.class) + public void testDatabase_020 () throws SQLException { + final WriteRelationalData write = new WriteRelationalData(conn); + Assert.assertEquals(1, + write.insertLecturer("goik", "Martin Goik", "goik@hdm-stuttgart.de")); + } + /** + * Second lecturer record having null email. + */ + @Test + public void testDatabase_030 () throws SQLException { + final WriteRelationalData write = new WriteRelationalData(conn); + + hahnId = write.insertLecturer("hahn", "Jens Hahn", null); + Assert.assertTrue(0 < hahnId); + } + /** + * Insert lecture "Software Development 1" + */ + @Test + public void testDatabase_040 () throws SQLException { + final WriteRelationalData write = new WriteRelationalData(conn); + + final int count = write.insertCourse( + 113105, goikId, "Software Development 1", "Introduction to Java"); + Assert.assertEquals(1, count); + } + /** + * Try inserting duplicate lecture "Software Development 1" + */ + @Test(expected = SQLIntegrityConstraintViolationException.class) + public void testDatabase_050 () throws SQLException { + final WriteRelationalData write = new WriteRelationalData(conn); + + final int count = write.insertCourse( + 113105, goikId, "Software Development 1", "Introduction to Java"); + Assert.assertEquals(1, count); + } + /** + * Insert lecture "Mathematics" + */ + @Test + public void testDatabase_060 () throws SQLException { + final WriteRelationalData write = new WriteRelationalData(conn); + + final int count = write.insertCourse( + 113109, hahnId, "Mathematics", null); + Assert.assertEquals(1, count); + } + /** + * Insert lecture "Structured data and applications" + */ + @Test + public void testDatabase_100 () throws SQLException { + final WriteRelationalData write = new WriteRelationalData(conn); + + final int count = write.insertCourse( + 113305, goikId, "Structured data and applications", null); + Assert.assertEquals(1, count); + } +} -- GitLab