Skip to content

13. SQL Server 2014

Nous abordons maintenant le portage sur SQL Server 2014 de ce qui a été fait avec MySQL.

13.1. Mise en place de l'environnement de travail

13.1.1. Environnement eclipse

Nous travaillerons avec l'environnement Eclipse suivant :

  

Les projets SQL Server ci-dessus seront trouvés dans le dossier [<exemples>/spring-database-config\sqlserver\eclipse].

Note : faire [Alt-F5] pour régénérer l'ensemble des projets Maven.

13.1.2. Génération des bases de données

Comme il a été fait avec Oracle et DB2, nous allons devoir installer le pilote JDBC de SQL Server dans le dépôt Maven local.

  

Le fichier [install.bat] contient le code suivant :

"%M2_HOME%\bin\mvn.bat" install:install-file -Dfile=sqljdbc4-3.0.jar -Dpackaging=jar -DgroupId=com.microsoft.sqlserver -DartifactId=sqljdbc4 -Dversion=4.0

où [%M2-HOME%] est le dossier d'installation de Maven (cf paragraphe 23.2, page 466). Après cette installation, le pilote JDBC de SQL Server peut être référencé dans les fichiers [pom.xml] par la dépendance suivante :


        <dependency>
            <groupId>com.microsoft.sqlserver</groupId>
            <artifactId>sqljdbc4</artifactId>
            <version>4.0</version>
</dependency>

Dans toute la suite, la connexion aux bases SQL SERVER se font avec les identifiants [sa / msde]. Lancez SQL Server et son client [MsManager] (cf paragraphe 23.9).

  • en [1], chargez le script SQL [<exemples>\spring-database-config\sqlserver\databases\dbproduits.sql] ;
  • en [2], il n'a pas été possible d'utiliser la même table [PRODUITS] pour les projets [spring-jdbc-01 à 03]. La raison en est que :
    • les projets [spring-jdbc-01 et 02] insèrent des lignes avec leurs clés primaires ;
    • le projet [spring-jdbc-03] insèrent des lignes sans clés primaires et s'attend à ce que le SGBD génère celles-ci. Pour cela, il faut que la clé primaire [ID] soit de type [Identity]. Or ce type dans SQL Server ne supporte que la génération automatique des clés primaires et n'autorise pas l'insertion d'une ligne avec une clé primaire fixée par l'utilisateur. Une erreur est alors signalée et je n'ai pas su la contourner. Les projets [spring-jdbc-01 et 02] utilisent la table [PRODUITS] sans génération automatique des clés primaires. Le projet [spring-jdbc-03] utilise la table [PRODUITS2] avec génération automatique des clés primaires.

Maintenant, exécutez les configurations :

  • [spring-jdbc-generic-01.IntroJdbc01] ;
  • [spring-jdbc-generic-01.IntroJdbc02] ;
  • [spring-jdbc-generic-03.JUnitTestDao1] ;
  • [spring-jdbc-generic-03.JUnitTestDao2] ;

Elles doivent toutes réussir.

Générons maintenant la base [dbproduitscategories]. Refaites pour [dbproduitscategories] la procédure réalisée pour créer [dbproduits]. Le script SQL à charger est à l'emplacement [<exemples>\spring-database-config\sqlserver\databases\ dbproduitscategories.sql] ;

  

Maintenant, exécutez les configurations :

  • [spring-jdbc-generic-04.JUnitTestDao] ;
  • [spring-jpa-generic-JUnitTestDao-openjpa] ;

Elles doivent réussir toutes les deux.

13.2. Configuration de la couche JDBC

 

Le projet [sqlserver-config-jdbc] configure la couche [JDBC] de l'architecture de tests suivante :

Le projet est analogue au projet de configuration [mysql-config-jdbc] de la couche JDBC du SGBD MySQL (cf paragraphe 3.3). Nous ne présentons que les modifications :

Le fichier [pom.xml] importe le pilote JDBC de SQL Server :


<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>dvp.spring.database</groupId>
    <artifactId>generic-config-jdbc</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>configuration generic jdbc</name>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.2.3.RELEASE</version>
    </parent>

    <dependencies>
        <!-- dépendances variables ********************************************** -->
        <!-- pilote JDBC du SGBD -->
        <dependency>
            <groupId>com.microsoft.sqlserver</groupId>
            <artifactId>sqljdbc4</artifactId>
            <version>4.0</version>
        </dependency>
        <!-- dépendances constantes ********************************************** -->
        ...
    </dependencies>
...
</project>
  • lignes 18-22 : le pilote JDBC de SQL Server ;

La seconde modification est dans la classe [ConfigJdbc] qui définit les identifiants d'accès aux bases :


    // paramètres de connexion
    public final static String DRIVER_CLASSNAME = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
    public final static String URL_DBPRODUITS = "jdbc:sqlserver://localhost\\SQLEXPRESS:1433;databaseName=dbproduits";
    public final static String USER_DBPRODUITS = "sa";
    public final static String PASSWD_DBPRODUITS = "msde";
    public final static String URL_DBPRODUITSCATEGORIES = "jdbc:sqlserver://localhost\\SQLEXPRESS:1433;databaseName=dbproduitscategories";
    public final static String USER_DBPRODUITSCATEGORIES = "sa";
public final static String PASSWD_DBPRODUITSCATEGORIES = "msde";

La troisième modification qui peut être apportée est celle du nombre maximal de paramètres qu'un [PreparedStatement] peut supporter :


    // nombre max de paramètres d'un [PreparedStatement]
    public final static int MAX_PREPAREDSTATEMENT_PARAMETERS = 2000;

Le test [JUnitTestPushTheLimits] génère des ordres SQL sur 5000 produits qui vont générer des [PreparedStatement] avec 5000 paramètres. MySQL avait supporté cette valeur. SQL Server a émis une erreur indiquant que cette limite était à 2100.

La quatrième modification est dans la table utilisée par le projet [spring-jdbc-03]. Ce n'est plus [PRODUITS] mais [PRODUITS2] :


    // ordres SQL [jdbc-03]
    public final static String V2_INSERT_PRODUITS = "INSERT INTO PRODUITS2(NOM, CATEGORIE, PRIX, DESCRIPTION) VALUES (?, ?, ?, ?)";
    public final static String V2_DELETE_ALLPRODUITS = "DELETE FROM PRODUITS2";
    public final static String V2_DELETE_PRODUITS = "DELETE FROM PRODUITS2 WHERE ID=?";
    public final static String V2_SELECT_ALLPRODUITS = "SELECT ID, NOM, CATEGORIE, PRIX, DESCRIPTION FROM PRODUITS2";
    public final static String V2_SELECT_PRODUIT_BYID = "SELECT NOM, CATEGORIE, PRIX, DESCRIPTION FROM PRODUITS2 WHERE ID=?";
    public final static String V2_SELECT_PRODUIT_BYNAME = "SELECT ID, CATEGORIE, PRIX, DESCRIPTION FROM PRODUITS2 WHERE NOM=?";
public final static String V2_UPDATE_PRODUITS = "UPDATE PRODUITS2 SET NOM=?, PRIX=?, CATEGORIE=?, DESCRIPTION=? WHERE ID=?";

13.3. Configuration de la couche JPA OpenJpa

 

Le projet [sqlserver-config-jpa-openjpa] configure la couche [JPA] de l'architecture de tests :

Le projet est analogue au projet de configuration [mysql-config-jpa-openjpa] de la couche JPA OpenJpa du SGBD MySQL (cf paragraphe 8.3). En effet, les deux SGBD utilisent l'annotation [@GeneratedValue(strategy = GenerationType.IDENTITY)] pour générer les clés primaires. Il y a deux modifications à faire. Elle est dans la définition du bean [jpaVendorAdapter] de la classe [ConfigJpa] :


    // le provider JPA
    @Bean
    public JpaVendorAdapter jpaVendorAdapter() {
        OpenJpaVendorAdapter openJpaVendorAdapter = new OpenJpaVendorAdapter();
        openJpaVendorAdapter.setShowSql(false);
        openJpaVendorAdapter.setDatabase(Database.SQL_SERVER);
        openJpaVendorAdapter.setGenerateDdl(true);
        return openJpaVendorAdapter;
}
  • ligne 6 : on indique à l'implémentation JPA qu'elle va travailler avec une base SQL Server. L'implémentation JPA va alors adopter et les types de données propriétaires et le SQL propriétaire de ce SGBD.

La seconde modification concerne les entités JPA associées aux tables [PRODUITS] et [PRODUITS2] :

  

L'entité [Produit] est associée à la table [PRODUITS] sans génération automatique des clés primaires (absence de notation [@GeneratedValue]) :


@Entity(name = "Produit1")
@Table(name = ConfigJdbc.TAB_PRODUITS)
public class Produit {

// champs
@Id
@Column(name = ConfigJdbc.TAB_PRODUITS_ID)
private Long id;

L'entité [Produit2] est associée à la table [PRODUITS2] avec génération automatique des clés primaires :


@Entity(name = "Produit2")
@Table(name = ConfigJdbc.TAB_PRODUITS2)
public class Produit2 {

// champs
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = ConfigJdbc.TAB_PRODUITS_ID)
private Long id;

Par ailleurs, le projet qui génère la base [dbproduits] doit être modifié pour indiquer qu'il y a maintenant deux entités JPA dans la base :

  

Le fichier [persistence.xml] évolue de la façon suivante :


<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
    <persistence-unit name="generic-jpa-entities-dbproduits" transaction-type="RESOURCE_LOCAL">
        <!-- entités JPA -->
        <class>generic.jpa.entities.dbproduits.Produit</class>
        <class>generic.jpa.entities.dbproduits.Produit2</class>
        <exclude-unlisted-classes>true</exclude-unlisted-classes>
    </persistence-unit>
</persistence>

Le projet [generic-create-dbproduits] est commun à tous les SGBD. La couche JPA de ceux étudiés précédemment n'avaient pas l'entité [Produit2]. On peut se demander alors si le fait de référencer une entité JPA inexistante ne va pas planter le projet pour ces SGBD. Les tests montrent que non.

Ces modifications faites, l'exécution de la configuration [spring-jpa-generic-JUnitTestDao-openjpa] doit réussir.

13.4. Configuration de la couche JPA Hibernate

 

Note : faire [Alt-F5] pour régénérer l'ensemble des projets Maven.

Le projet [sqlserver-config-jpa-hibernate] est analogue au projet [mysql-config-jpa-hibernate] (paragraphe 6.3) avec les mêmes modifications qui ont présidé au portage du [mysql-config-jpa-openjpa] vers le projet [sqlserver-config-jpa-openjpa] (paragraphe 8.3).

Ces modifications faites, l'exécution de la configuration [spring-jpa-generic-JUnitTestDao-hibernate-eclipselink] doit réussir.

 

Note : faire [Alt-F5] pour régénérer l'ensemble des projets Maven.

Le projet [sqlserver-config-jpa-eclipselink] est analogue au projet [mysql-config-jpa-eclipselink] (paragraphe 7.3) avec les mêmes modifications qui ont présidé au portage du [mysql-config-jpa-openjpa] vers le projet [sqlserver-config-jpa-openjpa] (paragraphe 8.3).

Ces modifications faites, l'exécution de la configuration [spring-jpa-generic-JUnitTestDao-hibernate-eclipselink] doit réussir.