Skip to content

20. 3 katmanlı mimaride MVC web uygulaması – Örnek 6, SQL Server Express

20.1. SQL Server Express veritabanı

Bu sürümde, SQL Server Express 2005 veritabanındaki kişi listesini, [http://msdn.microsoft.com/vstudio/express/sql/] adresinde bulunan tabloya yükleyeceğiz. Aşağıdaki ekran görüntüleri, SQL Server Express [http://www.sqlmanager.net/fr/products/mssql/manager] için EMS Manager Lite istemcisinden alınmıştır; SGBD SQL Server Express için ücretsiz bir yönetim istemcisidir.

Veritabanının adı [dbpersonnes]'tir. Bu veritabanında [PERSONNES] adlı bir tablo bulunmaktadır:

Image

[PERSONNES] tablosu, web uygulaması tarafından yönetilen kişilerin listesini içerecektir. Bu tablo, aşağıdaki SQL komutlarıyla oluşturulmuştur:

CREATE TABLE [dbo].[PERSONNES] (
  [ID] int IDENTITY(1, 1) NOT NULL,
  [VERSION] int NOT NULL,
  [NOM] varchar(30) COLLATE French_CI_AS NOT NULL,
  [PRENOM] varchar(30) COLLATE French_CI_AS NOT NULL,
  [DATENAISSANCE] datetime NOT NULL,
  [MARIE] tinyint NOT NULL,
  [NBENFANTS] tinyint NOT NULL,
  PRIMARY KEY CLUSTERED ([ID]),
  CONSTRAINT [PERSONNES_ck_NOM] CHECK ([NOM]<>''),
  CONSTRAINT [PERSONNES_ck_PRENOM] CHECK ([PRENOM]<>''),
  CONSTRAINT [PERSONNES_ck_NBENFANTS] CHECK ([NBENFANTS]>=(0))
)
ON [PRIMARY]
GO
  • 2. satır: [ID] birincil anahtarı tamsayı türündedir. IDENTITY özniteliği, tablonun ID sütununa değeri olmayan bir satır eklenirse, SQL Express'in bu sütun için kendisi bir tamsayı oluşturacağını belirtir. IDENTITY(1, 1) ifadesinde, ilk parametre birincil anahtar için olası ilk değerdir; ikinci parametre ise sayıların oluşturulmasında kullanılan artış değeridir.

[PERSONNES] tablosu aşağıdaki içeriğe sahip olabilir:

Image

[Personne] nesnesinin [dao] katmanımız tarafından eklenmesi sırasında, bu nesnenin [id] alanı, ekleme işleminden önce -1'e eşittir ve sonrasında -1'den farklı bir değere sahip olur; bu değer, [PERSONNES] tablosuna eklenen yeni satıra atanan birincil anahtardır. Bir örnek üzerinden bu değeri nasıl öğrenebileceğimize bakalım.

SQL siparişi

SELECT @@IDENTITY

komutu, tablonun ID alanına en son eklenen değeri öğrenmemizi sağlar. Bu komut, ekleme işleminden sonra çalıştırılmalıdır. Bu, SGBD, [Firebird] ve [Postgres] komutlarından farklıdır; bu komutlarda, ekleme işleminden önce eklenen kişinin birincil anahtar değeri isteniyordu, ancak bu, SGBD ve MySQL'te birincil anahtarın oluşturulmasına benzer. Bunu, veritabanına gönderilen SQL komutlarını bir araya getiren [personnes-sqlexpress.xml] dosyasında kullanacağız.

20.2. [dao] ve [service] katmanlarının Eclipse projesi

[SQL Server Express] veritabanını kullanan uygulamamızın [dao] ve [service] katmanlarını geliştirmek için aşağıdaki [mvc-personnes-06] Eclipse projesini kullanacağız:

Image

Bu proje, bir Tomcat web projesi değil, basit bir Java projesidir.


[src] klasörü


Bu klasör, [dao] ve [service] katmanlarının kaynak kodlarını içerir:

Image

Adında [sqlexpress] geçen tüm dosyalar, Firebird, Postgres ve MySQL sürümlerine göre değiştirilmiş olabilir veya olmayabilir. Aşağıda, yalnızca değiştirilenleri açıklayacağız.


[database] klasörü


Bu klasör, SQL Express kişi veritabanını oluşturma komut dosyasını içerir:

Image

-- SQL Sunucusu için Manager 2005 Lite (2.2.0.1)
-- ---------------------------------------
-- Ana B    ilgisayar : (yerel)\SQLEXPRESS
-- Veritabanı: dbpersonnes


--
-- PERSONNES tablosunun yapısı: 
--

CREATE TABLE [dbo].[PERSONNES] (
  [ID] int IDENTITY(1, 1) NOT NULL,
  [VERSION] int NOT NULL,
  [NOM] varchar(30) COLLATE French_CI_AS NOT NULL,
  [PRENOM] varchar(30) COLLATE French_CI_AS NOT NULL,
  [DATENAISSANCE] datetime NOT NULL,
  [MARIE] tinyint NOT NULL,
  [NBENFANTS] tinyint NOT NULL,
  CONSTRAINT [PERSONNES_ck_NBENFANTS] CHECK ([NBENFANTS]>=(0)),
  CONSTRAINT [PERSONNES_ck_NOM] CHECK ([NOM]<>''),
  CONSTRAINT [PERSONNES_ck_PRENOM] CHECK ([PRENOM]<>'')
)
ON [PRIMARY]
GO

--
-- PERSONNES tablosu veriler i (LIMIT 0,500)
--

SET IDENTITY_INSERT [dbo].[PERSONNES] ON
GO

INSERT INTO [dbo].[PERSONNES] ([ID], [VERSION], [NOM], [PRENOM], [DATENAISSANCE], [MARIE], [NBENFANTS])
VALUES 
  (1, 1, 'Major', 'Joachim', '19541113', 1, 2)
GO

INSERT INTO [dbo].[PERSONNES] ([ID], [VERSION], [NOM], [PRENOM], [DATENAISSANCE], [MARIE], [NBENFANTS])
VALUES 
  (2, 1, 'Humbort', 'Mélanie', '19850212', 0, 1)
GO

INSERT INTO [dbo].[PERSONNES] ([ID], [VERSION], [NOM], [PRENOM], [DATENAISSANCE], [MARIE], [NBENFANTS])
VALUES 
  (3, 1, 'Lemarchand', 'Charles', '19860301', 0, 0)
GO

SET IDENTITY_INSERT [dbo].[PERSONNES] OFF
GO

--
-- Dizinler için tanım: 
--

ALTER TABLE [dbo].[PERSONNES]
ADD PRIMARY KEY CLUSTERED ([ID])
WITH (
  PAD_INDEX = OFF,
  IGNORE_DUP_KEY = OFF,
  STATISTICS_NORECOMPUTE = OFF,
  ALLOW_ROW_LOCKS = ON,
  ALLOW_PAGE_LOCKS = ON)
ON [PRIMARY]
GO

[lib] klasörü


Bu klasör, uygulama için gerekli dosyaları içerir:

[sqljdbc.jar], SGBD ve [Sql Server Express] jdbc sürücülerinin mevcut olduğu dikkat çekmektedir. Tüm bu dosyalar, Eclipse projesinin Classpath paketinin bir parçasıdır.


20.3. [dao] katmanı

[dao] katmanı şu şekildedir:

Image

[Firebird] sürümüne göre sadece değişenleri sunuyoruz.

[personne-sqlexpress.xml] eşleme dosyası şu şekildedir:


<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE sqlMap
    PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN"
    "http://www.ibatis.com/dtd/sql-map-2.dtd">

<sqlMap>
    <!-- [Personne] sınıfı takma adı -->
    <typeAlias alias="Personne.classe" 
        type="istia.st.mvc.personnes.entites.Personne"/>
    <!-- eşleme tablosu [PERSONNES] - nesne [Personne] -->
    <resultMap id="Personne.map" 
        class="istia.st.mvc.personnes.entites.Personne">
        <result property="id" column="ID" />
        <result property="version" column="VERSION" />
        <result property="nom" column="NOM"/>
        <result property="prenom" column="PRENOM"/>
        <result property="dateNaissance" column="DATENAISSANCE"/>
        <result property="marie" column="MARIE"/>
        <result property="nbEnfants" column="NBENFANTS"/>
    </resultMap>
    <!-- tüm kişilerin listesi -->
    <select id="Personne.getAll" resultMap="Personne.map" > select ID, VERSION, NOM, 
        PRENOM, DATENAISSANCE, MARIE, NBENFANTS FROM PERSONNES</select>
    <!-- belirli bir kişiyi bulma -->
        <select id="Personne.getOne" resultMap="Personne.map" >select ID, VERSION, NOM, 
        PRENOM, DATENAISSANCE, MARIE, NBENFANTS FROM PERSONNES WHERE ID=#değer#</select>
    <!-- bir kişi ekle -->
    <insert id="Personne.insertOne" parameterClass="Personne.classe">
        insert into 
        PERSONNES(VERSION, NOM, PRENOM, DATENAISSANCE, MARIE, NBENFANTS) 
        VALUES(#sürüm#, #soyadı#, #adı#, #dateNaissance#, #evli#, 
         #nbEnfants#) 
        <selectKey keyProperty="id">
            select @@IDENTITY as value
        </selectKey>         
    </insert>
    <!-- bir kişiyi güncelle -->
    <update id="Personne.updateOne" parameterClass="Personne.classe"> update 
        PERSONNES set VERSION=#sürüm#+1, NOM=#soyadı#, PRENOM=#adı#, DATENAISSANCE=#dateNaissance#, 
        MARIE=#eş#, NBENFANTS=#nbEnfants# WHERE ID=#id# ve 
        VERSION=#sürüm#</güncelleme>
    <!-- bir kişiyi sil -->
    <delete id="Personne.deleteOne" parameterClass="int"> delete FROM PERSONNES WHERE 
        ID=#değer# </sil>
    <!-- en son eklenen kişinin [id] birincil anahtarının değerini al -->
    <select id="Personne.getNextId" resultClass="int">select 
        LAST_INSERT_ID()</select>
</sqlMap>

Bu dosya, aşağıdaki ayrıntılar dışında [personnes-firebird.xml] ile aynı içeriğe sahiptir:

  • SQL " Personne.insertOne " komutunda 29-37. satırlar değişmiştir:
  • SQL ekleme komutu, eklenen satırın birincil anahtar değerini alabilmeyi sağlayacak olan SELECT komutundan önce yürütülür
  • SQL ekleme komutunda, [PERSONNES] tablosunun ID sütunu için bir değer bulunmamaktadır

Bu durum, 20.1. paragrafında ele aldığımız ekleme örneğini yansıtmaktadır. Burada, 19.3. paragrafında MySQL için açıklanan, farklı iş parçacıkları tarafından yapılan eşzamanlı eklemeler sorunuyla karşılaşıldığına dikkat edilmelidir.

[dao] katmanının [DaoImplCommon] uygulama sınıfı, önceki üç sürümünkiyle aynıdır.

[dao] katmanının yapılandırması, SGBD ve [SQL Express]'e uyarlanmıştır. Dolayısıyla, [spring-config-test-dao-sqlexpress.xml] yapılandırma dosyası şu şekildedir:


<?xml version="1.0" encoding="ISO_8859-1"?>
<!DOCTYPE beans SYSTEM "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
    <!-- veri kaynağı DBCP -->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" 
        destroy-method="close">
        <property name="driverClassName">
            <value>com.microsoft.sqlserver.jdbc.SQLServerDriver</value>
        </property>
        <property name="url">
            <value>jdbc:sqlserver://localhost\\SQLEXPRESS:4000;databaseName=dbpersonnes</value>
        </property>
        <property name="username">
            <value>sa</value>
        </property>
        <property name="password">
            <value>msde</value>
        </property>
    </bean>
    <!-- SqlMapCllient -->
    <bean id="sqlMapClient" 
        class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
        <property name="dataSource">
            <ref local="dataSource"/>
        </property>
        <property name="configLocation">
            <value>classpath:sql-map-config-sqlexpress.xml</value>
        </property>
    </bean>
    <!-- katmana erişim sınıfı [dao] -->
    <bean id="dao" class="istia.st.mvc.personnes.dao.DaoImplCommon">
        <property name="sqlMapClient">
            <ref local="sqlMapClient"/>
        </property>
    </bean>
</beans>
  • 5-19. satırlar: [dataSource] bean'i artık, yöneticisi [sa] olan ve şifresi [msde] olan [SQL Express] ve [dbpersonnes] veritabanlarını işaret etmektedir. Okuyucu, bu yapılandırmayı kendi ortamına göre değiştirecektir.
  • 31. satır: [DaoImplCommon] sınıfı, [dao] katmanının uygulama sınıfıdır

11. satırın açıklanması gerekir:

            <value>jdbc:sqlserver://localhost\\SQLEXPRESS:4000;databaseName=dbpersonnes</value>
  • //localhost: SQL Express sunucusunun Java uygulamamızla aynı makinede olduğunu belirtir
  • \\SQLEXPRESS: SQL Sunucusunun bir örneğinin adıdır. Görünüşe göre aynı anda birden fazla örnek çalıştırılabilir. Bu nedenle, bağlantı kurduğumuz örneği adlandırmak mantıklı görünüyor. Bu ad, genellikle SQL Express ile birlikte kurulan [SQL Server Configuration Manager] aracılığıyla elde edilebilir:

Image

Image

  • 4000: SQL Express'in dinleme bağlantı noktası. Bu, sunucunun yapılandırmasına bağlıdır. Varsayılan olarak dinamik bağlantı noktalarıyla çalışır; dolayısıyla bağlantı noktaları önceden bilinmez. Bu durumda, JDBC URL'sinde bağlantı noktası belirtilmez. Burada, 4000 numaralı sabit bir bağlantı noktası kullandık. Bu, aşağıdaki yapılandırma ile elde edilir:
  • dataBaseName özniteliği, çalışmak istediğimiz veritabanını belirler. Bu, EMS istemcisiyle oluşturulan veritabanıdır:

Image

Bu değişiklikler yapıldıktan sonra testlere geçilebilir.

20.4. [dao] ve [service] katmanlarının testleri

[dao] ve [service] katmanlarının testleri, [Firebird] sürümüyle aynıdır. Elde edilen sonuçlar şunlardır:

[DaoImplCommon] uygulamasında testlerin başarıyla geçtiği görülmektedir. SGBD ve [Firebird] sürümlerinde olduğu gibi bu sınıfı türetmemize gerek kalmayacaktır.

20.5. [web] uygulamasının testleri

SGBD ve [SQL Server Express] ile web uygulamasını test etmek için, önceki web projelerini oluştururken kullandığımız yönteme benzer şekilde bir Eclipse projesi ([mvc-personnes-06B]) oluşturuyoruz.

[mvc-personnes-05B] web projesini Tomcat'e dağıtıyoruz:

SGBD SQL Express sunucusu başlatılır. [PERSONNES] tablosunun içeriği şu şekildedir:

Image

Tomcat da sırayla başlatılır. Bir tarayıcı kullanarak [http://localhost:8080/mvc-personnes-06B] URL'sini çağırıyoruz:

Image

Şu bağlantıyla [Ajout] bağlantısıyla yeni bir kişi ekliyoruz:

Veritabanında eklenmiş olup olmadığını kontrol ediyoruz:

Image

Okuyucunun başka testler yapması önerilir: [modification, suppression].