Avatar billede hojgaard Nybegynder
17. marts 2003 - 18:02 Der er 17 kommentarer og
1 løsning

Custom tag > database

Hej,

Jeg har endelig fået lavet mit første tag, der henter alle lande i en database, og viser dem i en <select> boks.

Mit tag står selv for at tilgå databasen.

Spørgsmålet er nu:
hvor "pænt" er det at lade mit tag tilgå databasen direkte?

Er der ikke noget galt i det, eller bør jeg lade en anden java-klasse står for denne del?
Avatar billede arne_v Ekspert
17. marts 2003 - 18:59 #1
Umiddelbart vil jeg mene det er hip som hap om du har en klasse
mellem din tag kode og din database dgang.

Men lav et lille eksperiment og prøv at lave begge muligheder. Hvis
den ekstra klasse kan laves så generel at man sparer kode
linier i en større applikation, så er det en god ide.

Er du skiftet til DataSource via JNDI lookup ? Fordi det er
pænt at bruge det fremfor DriverManager !

Hvis din data adgang skal være det mest avancerede J2EE kan
diske op med, så skal det jo være:

JSP --- session bean --- entiry bean

istedetfor direkte JDBC.
Avatar billede hojgaard Nybegynder
17. marts 2003 - 19:13 #2
Hej arne_v

Jeg er netop lige nu igang med at prøve at flytte database-delen væk fra mit tag, og ud i en separat klasse. Umiddelbart synes jeg design-mæssigt, at det er forkert at alle tag's selv skal stå for at skabe databaseforbindelsen.
Derfor også mit spørgsmål her på Eksperten.

Jeg har ikke skiftet helt over til DataSource endnu, men det er planen at gøre det. Problemet er, at jeg i min jsp-side får en fejl når jeg bruger DataSource, selvom jeg fint kan hente fra databasen.

Det virker, ligesom custom tags, som noget helt genialt!

Desværre er jeg helt grøn på J2EE endnu... så den helt forkromede løsning bliver det nok ikke ;o)
Avatar billede arne_v Ekspert
17. marts 2003 - 19:38 #3
Det vil være en performance mæssig katastrofe, hvis hver tag skal
lave en connection.

Men connection jo genbruges. Lige fra en static og et != bull test,
over et singleton pattern til en connection pool.

Hvis du bruget DataSource, så har du gratis en connection pool.

Hvilken fejl får du med DataSource ?
Avatar billede arne_v Ekspert
17. marts 2003 - 19:38 #4
!= null

:-)
Avatar billede hojgaard Nybegynder
17. marts 2003 - 20:11 #5
Jeg prøvede lige at lege med DataSource igen...
og nu virker det som det skal :o)

Nu skal jeg bare have tilpasset hele koden, så alle der henter en connection, også får lukket den igen.

Desuden har jeg fået flyttet hele database-delen væk fra mit eget tag, så det nu foregår i min DBAdmin klasse. Synes det virker pænere...
Avatar billede hojgaard Nybegynder
17. marts 2003 - 20:19 #6
Nu troede jeg lige det virkede... men nej.
Jeg får følgende fejl:

java.sql.SQLException: [Microsoft][SQLServer 2000 Driver for JDBC]Object has been closed.

Kender du den?
Avatar billede arne_v Ekspert
17. marts 2003 - 20:23 #7
Nu ligger jeg lige dine 20:11 og 20:19 indlæg sammen.

Du skal ikke close de connections du henter med DataSource getConnection,
da de skal genbruges !
Avatar billede hojgaard Nybegynder
17. marts 2003 - 20:28 #8
ahhh... jeg troede man lukkede dem, for at få connection tilbage i pool'en igen.I min ellers udemærkede bog står der:

"...when the application calls the close() method, the physical connection to the database is not closed; instead, the pooled connection is returned to the pool."
Avatar billede hojgaard Nybegynder
17. marts 2003 - 20:28 #9
Nu har du vist efterhånden længe fortjent dine point :o)
Avatar billede arne_v Ekspert
17. marts 2003 - 20:34 #10
Det var faktisk også hvad jeg ville forvente.

Men fejl-beskeden antyder ligesom noget andet.

Det er muligt at det er server specifik.
Avatar billede hojgaard Nybegynder
17. marts 2003 - 21:01 #11
Jeg har fundet ud af hvorfor jeg fik fejlen.
Lidt kode:
...
...
Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
ResultSet rs = stmt.executeQuery(query);

con.close();
return rs;
...

Det er åbenbart et problem, når jeg lukker for connection, og stadig arbejder med det ResultSet jeg får retur... fatter ikke hvorfor, men det virker hvis jeg gør arbejdet med ResultSet færdig inden jeg lukker Connection.
Avatar billede arne_v Ekspert
17. marts 2003 - 21:26 #12
Ah. Så der er alligevel en logisk forklaring.

Connection pool virker OK (hjeg var bange for at den bare havde
sendt et DriverManager Connection objekt med over og at den fysiske
connection blev lukket.
Avatar billede arne_v Ekspert
17. marts 2003 - 21:29 #13
Og du kan ikke arnejde med et ResultSet, når Connection er lukket.

Hverken med DriverManager eller med DataSource.

ResultSet er kun en handle til query output (en cursor i
traditionel embedded SQL).

Prøv og forestil dig at der skal returneres 100 millioner
records.  executeQuery læser ikke alle records op i memory
i ResultSet.

rs.next() henter en record af gangen.

Derfor skal connection være åben så længe man bruger
ResultSet'et.

Hvis man laver et forward and backwards scrollable ResultSet, så
læses alle data op i memory.

Det er derfor ikke smart med mange records.
Avatar billede arne_v Ekspert
17. marts 2003 - 22:26 #14
Men det er faktisk lidt interessant det med close.

Java API Doc siger ikke noget om emnet.

Jaba tutorial (http://developer.java.sun.com/developer/Books/JDBCTutorial/index.html)
bruger close.
Avatar billede arne_v Ekspert
17. marts 2003 - 22:38 #15
Ah.

JDBC 3.0 Specification section 11.4:

A basic DataSource implementation, that is, one that does not implement
connection pooling, is typically provided by a JDBC driver vendor. In a basic
DataSource implementation, the following are true:
n The DataSource.getConnection method creates a new Connection object
that represents a physical connection and encapsulates all of the work to set up
and manage that connection.
n The Connection.close method shuts down the physical connection and frees
the associated resources.
In a DataSource implementation that includes connection pooling, a great deal
happens behind the scenes. In such an implementation, the following are true:

n The DataSource.getConnection method calls
PooledConnection.getConnection to get a logical handle to an underlying
physical connection. The overhead of setting up a new physical connection is
incurred only if there are no existing connections available in the connection pool.
When a new physical connection is needed, the connection pool manager will call
the ConnectionPoolDataSource method getPooledConnection to create
one. The work to manage the physical connection is delegated to the
PooledConnection object.
n The Connection.close method closes the logical handle, but the physical
connection is maintained. The connection pool manager is notified that the
underlying PooledConnection object is now available for reuse. If the
application attempts to reuse the logical handle, the Connection implementation
throws an SQLException.
Avatar billede arne_v Ekspert
17. marts 2003 - 22:40 #16
Hvilket på almindeligt dansk må betyde at en DataSource Connection
som der ikke ligger en connection pool bagved vil en close
lukke fysisk. Men for en DataSource Connection som derligger en connection
pool bagved vil en close ikke lukke fysisk.

Og det er et krav i specifikationen.

Alle servere bruger connection pool, så det bør være safe at kalde
close.

[jeg plejer bare ikke at gøre det]
Avatar billede hojgaard Nybegynder
18. marts 2003 - 08:51 #17
1000 tak arne_v!

Så fik vi vist afklaret, at vi bør lukke for connection, så den kan stå til rådighed for en anden der gerne vil ned i databasen.
Avatar billede arne_v Ekspert
18. marts 2003 - 09:00 #18
Den bliver selvfølgelig frigjordt selvom man ikke kalder close når
connection objektet ryger ud af scope.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester