



<html>
<head>
  <title>javabog.dk -  - JDBC - databaseadgang</title>
  <link rev="stylesheet" type="text/css" href="../typografi.css">
  <meta name="description" content="Lærebog i Java. Af Jacob Nordfalk. Udkommet hos Forlaget Globe">
  <meta name="keywords" content="designmønster, programmering, OOP, objekter, klasser, objektorienteret programmering, Java, JSP, lærebog, UML, IT">
</head>
<body bgcolor="#ffffff">



<a href='http://javabog.dk/'>javabog.dk</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href='kapitel19.jsp'>&lt;&lt; forrige</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href='indhold.jsp'>indhold</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href='kapitel21.jsp'>n&aelig;ste &gt;&gt;</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href='kode/'>programeksempler</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href='../index_OOP.html'>om bogen</a>

<H1 CLASS="western" STYLE="">20 <a name='afsn20'></a>JDBC -
databaseadgang</H1>
<P CLASS="kapiteloversigt-western">Indhold:</P>
<UL>
  <LI><P CLASS="kapiteloversigt-western">F&aring; kontakt til en
  database fra Java</P>
  <LI><P CLASS="kapiteloversigt-western">Kommandoer til en database</P>
  <LI><P CLASS="kapiteloversigt-western">Foresp&oslash;rgsler til en
  database</P>
</UL>
<P CLASS="kapiteloversigt-western">Kapitlet foruds&aelig;ttes ikke i
resten af bogen.</P>
<P CLASS="kapiteloversigt-western">Foruds&aelig;tter <a href='kapitel14.jsp'>kapitel 14</a>, Undtagelser
og lidt kendskab til databaser og databasesproget SQL (Structured
Query Language) og at du har en fungerende database, som du
&oslash;nsker adgang til fra Java.</P>


<P CLASS="western" STYLE="">Adgang til en
database fra Java sker gennem et s&aelig;t klasser, der under et
kaldes JDBC (Java DataBase Connectivity) - en platformuafh&aelig;ngig
pendant til Microsoft ODBC (Open DataBase Connectivity). Klasserne
ligger i pakken java.sql, s&aring; kildetekstfiler, der arbejder med
databaser, skal starte med:</P>
<PRE CLASS="kode-western">  import java.sql.*;</PRE><H2 CLASS="western">
20.1 <a name='afsn20.1'></a>Kontakt til databasen</SPAN></H2>
<P CLASS="western">At f&aring; kontakt til databasen er m&aring;ske
det sv&aelig;reste skridt. Det best&aring;r af to led:</P>
<OL>
  <LI><P CLASS="western">Indl&aelig;se databasedriveren</P>
  <LI><P CLASS="western">Etablere forbindelsen</P>
</OL>
<P CLASS="western">Indl&aelig;sning af driveren sker, ved at bede
systemet indl&aelig;se den p&aring;g&aelig;ldende klasse, der
derefter registrerer sig selv i JDBC-systemets driver-manager. Er det
f.eks. en Oracle-database, skriver man:</P>
<PRE CLASS="kode-western">  Class.forName(&quot;oracle.jdbc.driver.OracleDriver&quot;);</PRE><P CLASS="western">
Ofte skal man have en jar-fil (et Java-ARkiv, en samling klasser
pakket i zip-formatet) med en driver fra producenten. Nyeste drivere
kan findes p&aring; <A CLASS="western" HREF="http://java.sun.com/jdbc">http://java.sun.com/jdbc</A>
. 
</P>
<P CLASS="western">For en Oracle-database hedder filen classes12.zip
og passer til en bestemt udgave af Oracle-databasen. Bruger man
Oracle JDeveloper, er den som standard med i projektets klassesti.
Ellers skal den f&oslash;jes til CLASSPATH (i JBuilder g&oslash;res
det under Project Properties, Paths, Required Libraries)</P>
<P CLASS="western">Herefter kan man oprette forbindelsen med (for en
Oracle-database):</P>
<PRE CLASS="kode-western">Connection forb = DriverManager.getConnection(
  &quot;jdbc:oracle:thin:@oracle.cv.ihk.dk:1521:student&quot;,&quot;brugernavn&quot;,&quot;adgangskode&quot;);</PRE><P CLASS="western">
F&oslash;rste parameter er en URL til databasen. Den best&aring;r af
en protokol (&quot;jdbc&quot;), underprotokol (&quot;oracle&quot;)
og noget mere, der afh&aelig;nger af underprotokollen. I dette
tilf&aelig;lde angiver det, at databasen ligger p&aring; maskinen
oracle.cv.ihk.dk port 1521 og hedder student.</P>
<P CLASS="western">Anden og tredje parameter er brugernavn og
adgangskode.</P>
<H3 CLASS="western">20.1.1 <a name='afsn20.1.1'></a>JDBC-ODBC-broen under Windows</H3>
<P CLASS="western">Med Java under Windows f&oslash;lger en standard
JDBC-ODBC-bro med, s&aring; man kan kontakte alle datakilder
defineret under ODBC. Denne driver indl&aelig;ses med:</P>
<PRE CLASS="kode-western">  Class.forName(&quot;sun.jdbc.odbc.JdbcOdbcDriver&quot;);</PRE><P CLASS="western">
N&aring;r forbindelsen oprettes, angiver man den &oslash;nskede
datakildes navn. Husk, at datakildens navn  (her &quot;datakilde1&quot;)
f&oslash;rst skal v&aelig;re defineret i Windows' Kontrolpanel under
ODBC:</P>
<PRE CLASS="kode-western">  Connection forb = DriverManager.getConnection(&quot;jdbc:odbc:datakilde1&quot;);</PRE><P CLASS="western">
Bem&aelig;rk, at ODBC er en ret langsom protokol. Har du brug for
bedre ydelse b&oslash;r du finde en driver, der kommunikerer direkte
med databasen, i stedet for at bruge JDBC-ODBC.</P>
<H2 CLASS="western">20.2 <a name='afsn20.2'></a>Kommunikere med databasen</SPAN></H2>
<P CLASS="western">N&aring;r vi har en forbindelse, kan vi oprette et
&quot;statement&quot;-objekt, som vi kan sende kommandoer og
foresp&oslash;rgsler til databasen med:</P>
<PRE CLASS="kode-western">  Statement stmt = forb.createStatement();</PRE><P CLASS="western">
Der kan opst&aring; forskellige undtagelser af typen SQLException,
der skal fanges.</P>
<H3 CLASS="western">20.2.1 <a name='afsn20.2.1'></a>Kommandoer</H3>
<P CLASS="western">SQL-kommandoer, der ikke giver et svar tilbage i
form af data, som INSERT, UPDATE, DELETE, CREATE TABLE og DROP TABLE,
sendes med executeUpdate()-metoden.</P>
<P CLASS="western">Her opretter vi f.eks. tabellen &quot;kunder&quot;
og inds&aelig;tter et par r&aelig;kker:</P>
<PRE CLASS="kode-western">import java.sql.*;
public class SimpeltDatabaseeksempel
{
  public static void main(String[] arg) throws Exception
  {
<I>    // Udskift med din egen databasedriver og -URL</I>
    Class.forName(&quot;sun.jdbc.odbc.JdbcOdbcDriver&quot;);
    Connection forb = DriverManager.getConnection(&quot;jdbc:odbc:datakilde1&quot;);
    Statement stmt = forb.createStatement();

<B>    stmt.executeUpdate(&quot;create table KUNDER (NAVN varchar(32), KREDIT float)&quot; );</B>

<B>    stmt.executeUpdate(&quot;insert into KUNDER values('Jacob', -1799)&quot;);</B>
<B>    stmt.executeUpdate(&quot;insert into KUNDER values('Brian', 0)&quot;);</B>
  }
}</PRE><P CLASS="western">
Oftest har man data gemt i nogle variabler. S&aring; skal man s&aelig;tte
en streng sammen, der giver den &oslash;nskede SQL-kommando:</P>
<PRE CLASS="kode-western">String navn = &quot;Hans&quot;;
int kredit = 500;

<I>// inds&aelig;t data fra variablerne navn og kredit</I>
stmt.executeUpdate(&quot;insert into KUNDER values('&quot;<B>+navn+</B>&quot;', &quot;<B>+kredit+</B>&quot;)&quot;);</PRE><H3 CLASS="western">
20.2.2 <a name='afsn20.2.2'></a>Foresp&oslash;rgsler</H3>
<P CLASS="western">SQL-foresp&oslash;rgslen SELECT udf&oslash;res med
metoden executeQuery():</P>
<PRE CLASS="kode-western">  ResultSet rs = stmt.executeQuery(&quot;select NAVN, KREDIT from KUNDER&quot;);</PRE><P CLASS="western">
Den giver et ResultSet-objekt, der repr&aelig;senterer svaret p&aring;
foresp&oslash;rgslen (for at f&aring; alle kolonner kunne vi ogs&aring;
skrive  &quot;select * from KUNDER&quot;). Data hentes fra objektet
s&aring;ledes:</P>
<PRE CLASS="kode-western">  while (<B>rs.next()</B>)
  {
    String navn = <B>rs.getString(&quot;NAVN&quot;)</B>;
    double kredit = <B>rs.getDouble(&quot;KREDIT&quot;)</B>;
    System.out.println(navn+&quot; &quot;+kredit);
  }</PRE><P CLASS="western">
Man kalder alts&aring; next() for at f&aring; n&aelig;ste r&aelig;kke
i svaret, l&aelig;ser de enkelte celler ud fra kolonnenavnene
(eller kolonnenumrene, regnet fra 1 af), hvorefter man g&aring;r
videre til n&aelig;ste r&aelig;kke med next() osv. N&aring;r next()
returnerer false, er der ikke flere r&aelig;kker at l&aelig;se.</P>
<H2 CLASS="western">20.3 <a name='afsn20.3'></a>Adskille database- og programlogik</SPAN></H2>
<P CLASS="western">Det er en god id&eacute; at indkapsle
databasearbejdet &eacute;t sted, f.eks. i en klasse, s&aring;dan at
resten af programmet kan fungere, selvom databasens adresse eller
struktur skulle &aelig;ndre sig. 
</P>
<P CLASS="western">Ofte vil man have en klasse for hver tabel i
databasen, s&aring;dan at hvert objekt kommer til at svare til en
r&aelig;kke. Herunder har vi lavet klassen Kunder, svarende til
tabellen KUNDER:</P>
<PRE CLASS="kode-western">public class Kunde
{
<B>  String navn;</B>
<B>  double kredit;</B>

  public Kunde(String n, double k)
  {
    navn = n;
    kredit = k;
  }

  public String toString()
  {
    return navn+&quot;: &quot;+kredit+&quot; kr.&quot;;
  }
}</PRE>
<P CLASS="western">Klassen, der varetager forbindelsen til databasen,
b&oslash;r have metoder, der svarer til de kommandoer og
foresp&oslash;rgsler, resten af programmet har brug for. Hvis
databasen &aelig;ndrer sig, er det kun denne klasse, der skal rettes
i:</P>
<PRE CLASS="kode-western">import java.sql.*;
import java.util.*;

public class Databaseforbindelse
{
  private Connection forb;
  private Statement stmt;

  public Databaseforbindelse() throws Exception
  {
    Class.forName(&quot;oracle.jdbc.driver.OracleDriver&quot;);
    Connection forb = DriverManager.getConnection(
      &quot;jdbc:oracle:thin:@oracle.cv.ihk.dk:1521:student&quot;,&quot;brugernavn&quot;,&quot;kode&quot;);
    stmt = forb.createStatement();
  }

<B>  public void sletAlleData()</B> throws SQLException
  {
    stmt.execute(&quot;truncate table KUNDER&quot;);
  }

<B>  public void opretTestdata()</B> throws SQLException
  {
    try { <SPAN STYLE="font-weight: medium"><I>// hvis tabellen allerede eksisterer opst&aring;r der en SQL-udtagelse</I></SPAN>
      stmt.executeUpdate(
        &quot;create table KUNDER (NAVN varchar(32), KREDIT float)&quot; );
    } catch (SQLException e) {
      System.out.println(&quot;Kunne ikke oprette tabel: &quot;+e);
    }
    stmt.executeUpdate(&quot;insert into KUNDER values('Jacob', -1799)&quot;);
    stmt.executeUpdate(&quot;insert into KUNDER values('Brian', 0)&quot;);
  }

<B>  public void inds&aelig;t(Kunde k)</B> throws SQLException
  {
    stmt.executeUpdate(&quot;insert into KUNDER (NAVN,KREDIT) values('&quot; 
      + k.navn + &quot;', &quot; + k.kredit + &quot;)&quot;);
  }

<B>  public ArrayList&lt;Kunde&gt; hentAlle()</B> throws SQLException
  {
    ArrayList<B>&lt;Kunde&gt;</B> alle = new ArrayList<B>&lt;Kunde&gt;</B>();
<B>    ResultSet rs = stmt.executeQuery</B><SPAN STYLE="font-weight: medium">(&quot;select NAVN, KREDIT from KUNDER&quot;);</SPAN>
<B>    while (rs.next())</B>
<B>    {</B>
      <I>// brug kolonneindeks i stedet for kolonnenavn</I>
      Kunde k = new Kunde( <B>rs.getString(1), rs.getDouble(2)</B>);
      alle.add(k);
<B>    }</B>
    return alle;
  }
}</PRE><P CLASS="western">
Klassen lader kalderen om at h&aring;ndtere de mulige undtagelser.
Det er fornuftigt, da det ogs&aring; er kalderen, der skal
fort&aelig;lle fejlen til brugeren og evt. beslutte, om programmet
skal afbrydes.</P>
<P CLASS="western" STYLE="">Her er et
program, der bruger Databaseforbindelse. F&oslash;rst opretter det
forbindelsen og henter alle poster, dern&aelig;st sletter det alt og
inds&aelig;tter en enkelt post. Hvis der opst&aring;r en fejl,
udskrives &quot;Problem med database&quot; og programmet afbrydes.</P>
<PRE CLASS="kode-western">import java.util.*;

public class BenytDatabaseforbindelse
{
  public static void main(String[] arg)
  {
    try {
      Databaseforbindelse dbf = new Databaseforbindelse();

      dbf.opretTestdata(); <I>// fjern hvis tabellen allerede findes</I>
      ArrayList<B>&lt;Kunde&gt; </B>l = dbf.hentAlle();
      System.out.println(&quot;Alle data: &quot;+l);
      dbf.sletAlleData();

      dbf.inds&aelig;t( new Kunde(&quot;Kurt&quot;,1000) );
      System.out.println(&quot;Alle data nu: &quot;+ dbf.hentAlle());

    } catch(Exception e) {
      System.out.println(&quot;Problem med database: &quot;+e);
      e.printStackTrace();
    }
  }
}</PRE>
<HR>
<PRE CLASS="kode-western">Alle data: [Jacob: -1799.0 kr., Brian: 0.0 kr.]
Alle data nu: [Kurt: 1000.0 kr.]</PRE><H2 CLASS="western">
20.4 <a name='afsn20.4'></a>Opgaver</SPAN></H2>
<OL>
  <LI><P CLASS="western">&AElig;ndr SimpeltDatabaseeksempel, s&aring;
  den ogs&aring; laver en SQL-foresp&oslash;rgsel.</P>
  <LI><P CLASS="western">Udvid Databaseforbindelse, s&aring; den kan
  s&oslash;ge efter en kunde ud fra kundens navn (antag, at
  navnet er en prim&aelig;rn&oslash;gle, s&aring; der ikke kan v&aelig;re
  flere kunder med samme navn).</P>
  <LI><P CLASS="western">Udvid Databaseforbindelse, s&aring; den kan
  give en liste med alle kunder med negativ kredit.</P>
  <LI><P CLASS="western">Lav et program, der holder styr p&aring; en
  musiksamling vha. en database. Databasen skal have tabellen
  UDGIVELSER med kolonnerne &aring;r, navn, gruppe og pladeselskab.
  Opret en tilsvarende klasse, der repr&aelig;senterer en Udgivelse
  (int &aring;r, String navn, String gruppe, String
  pladeselskab). Lav en passende Databaseforbindelse og et (evt.
  grafisk) program, der arbejder med musikdatabasen.</P>
  <LI><P CLASS="western">Ret databasen i forrige opgave til at have
  tabellen UDGIVELSER med kolonnerne &aring;r, navn og gruppeID,
  tabellen GRUPPER med kolonnerne gruppeID, navn, pladeselskab.
  Hvordan skal Databaseforbindelse &aelig;ndres? Beh&oslash;ves der
  blive &aelig;ndret i resten af programmet? Hvorfor?</P>
  <LI><P CLASS="western">Udvid programmet, s&aring; hver gruppe har en
  genre som f.eks. rock, tekno, klassisk (tabellen GRUPPER
  udvides med genreID og tabellen GENRER oprettes med kolonnerne
  genreID og navn).</P>
</OL>

<H2 CLASS="western" STYLE="">20.5 <a name='afsn20.5'></a>Avanceret</SPAN></H2>

	    Dette afsnit er ikke omfattet af Åben Dokumentslicens.<br>
	    Du skal <a href="/index_OOP.html#bestil">købe</a> bogen for at
	    måtte læse dette afsnit.

  <form action="http://javabog.dk/OOP3/kapitel20.jsp#afsn20.5">
  <input type='checkbox' name='vis' value='20.5'>Jeg erklærer, at jeg allerede har købt bogen<br />
  <input type='checkbox' name='vis' value='20.5'>Jeg lover at anskaffe den i nær fremtid.<br />
  <input type='submit' value='Vis mig dette afsnit'>
  </form>

	  <H3 CLASS="western">20.5.1 <a name='afsn20.5.1'></a>Forpligtende eller ej? (commit)</H3>

	    Dette afsnit er ikke omfattet af Åben Dokumentslicens.<br>
	    Du skal <a href="/index_OOP.html#bestil">købe</a> bogen for at
	    måtte læse dette afsnit.

  <form action="http://javabog.dk/OOP3/kapitel20.jsp#afsn20.5.1">
  <input type='checkbox' name='vis' value='20.5.1'>Jeg erklærer, at jeg allerede har købt bogen<br />
  <input type='checkbox' name='vis' value='20.5.1'>Jeg lover at anskaffe den i nær fremtid.<br />
  <input type='submit' value='Vis mig dette afsnit'>
  </form>

	  <H3 CLASS="western">20.5.2 <a name='afsn20.5.2'></a>Optimering</H3>

	    Dette afsnit er ikke omfattet af Åben Dokumentslicens.<br>
	    Du skal <a href="/index_OOP.html#bestil">købe</a> bogen for at
	    måtte læse dette afsnit.

  <form action="http://javabog.dk/OOP3/kapitel20.jsp#afsn20.5.2">
  <input type='checkbox' name='vis' value='20.5.2'>Jeg erklærer, at jeg allerede har købt bogen<br />
  <input type='checkbox' name='vis' value='20.5.2'>Jeg lover at anskaffe den i nær fremtid.<br />
  <input type='submit' value='Vis mig dette afsnit'>
  </form>

	  <H3 CLASS="western" STYLE="">20.5.3 <a name='afsn20.5.3'></a>Metadata</H3>

	    Dette afsnit er ikke omfattet af Åben Dokumentslicens.<br>
	    Du skal <a href="/index_OOP.html#bestil">købe</a> bogen for at
	    måtte læse dette afsnit.

  <form action="http://javabog.dk/OOP3/kapitel20.jsp#afsn20.5.3">
  <input type='checkbox' name='vis' value='20.5.3'>Jeg erklærer, at jeg allerede har købt bogen<br />
  <input type='checkbox' name='vis' value='20.5.3'>Jeg lover at anskaffe den i nær fremtid.<br />
  <input type='submit' value='Vis mig dette afsnit'>
  </form>

	  <H3 CLASS="western">
20.5.4 <a name='afsn20.5.4'></a>Opdatering og navigering i ResultSet-objekter</H3>

	    Dette afsnit er ikke omfattet af Åben Dokumentslicens.<br>
	    Du skal <a href="/index_OOP.html#bestil">købe</a> bogen for at
	    måtte læse dette afsnit.

  <form action="http://javabog.dk/OOP3/kapitel20.jsp#afsn20.5.4">
  <input type='checkbox' name='vis' value='20.5.4'>Jeg erklærer, at jeg allerede har købt bogen<br />
  <input type='checkbox' name='vis' value='20.5.4'>Jeg lover at anskaffe den i nær fremtid.<br />
  <input type='submit' value='Vis mig dette afsnit'>
  </form>

	  

<a href='http://javabog.dk/'>javabog.dk</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href='kapitel19.jsp'>&lt;&lt; forrige</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href='indhold.jsp'>indhold</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href='kapitel21.jsp'>n&aelig;ste &gt;&gt;</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href='kode/'>programeksempler</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href='../index_OOP.html'>om bogen</a>
<hr>
<font size=-2>http://javabog.dk/ - <b></b> af Jacob Nordfalk.
<br>
  Licens og kopiering under <a href='http://www.linuxbog.dk/licens.html'>&Aring;ben Dokumentlicens</a> (&Aring;DL)
  hvor intet andet er nævnt (82% af værket).
</font>
<br>
Ønsker du at se de sidste 18% af dette værk (199974 tegn)
skal du købe bogen. Så får du pæne figurer og layout, stikordsregister og en trykt bog med i købet.
<!-- netlæser: Wget/1.10, autoHent: true  -->
     

</body>
</html>
