web-dev-qa-db-fra.com

MyBatis 3 - Récupère la chaîne SQL du mappeur

Je voudrais utiliser MyBatis3 uniquement pour produire la chaîne SQL (À l'aide du mappage xml), mais l'obtention de SQL i n'est pas valide.

Exemple, j'obtiens la chaîne SQL:

SELECT * FROM USER WHERE NAME = john

Dans ce sql n'est pas présent le 'char entourant la valeur de chaîne john

dans mybatis.xml :

...
    <mappers>
        <mapper resource="sql1.xml"/>
    </mappers>
...

sql1.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

   <mapper namespace="sql1">
       <select id="select1" parameterType="map" resultType="String" >
           SELECT * FROM USERS
           WHERE 
           name LIKE ${name} AND num = ${number}
       </select>
   </mapper>

dans MyBatisSql.Java :

SqlSessionFactory sessionFactory = ConnectionFactory.getSqlSessionFactory();
Configuration configuration = sessionFactory.getConfiguration();

Map pars = new HashMap<String, Object>();
pars.put("name", "john");    
pars.put("number", 1345);

MappedStatement ms = configuration.getMappedStatement("sql1.select1);   
BoundSql boundSql = ms.getBoundSql(params);
String sql = boundSql.getSql();
System.out.println(sql);

le résultat est

SELECT * FROM USERS
WHERE 
name LIKE john AND num = 12345

dans ce SQL, la chaîne john , n'est pas entourée par le 'charso n'est pas un code SQL valide (mon but est uniquement de produire une chaîne SQL valide à l'aide de myBatis). J'aimerais avoir:

SELECT * FROM USERS
WHERE 
name LIKE 'john' AND num = 12345

merci

14
Lof

Vous devez utiliser # {nom} au lieu de $ {nom}

L'exemple ci-dessous générera un code SQL valide

<mapper namespace="sql1">
    <select id="select1" parameterType="map" resultType="String" >
        SELECT * FROM USERS
        WHERE 
        name LIKE #{name} AND num = #{number}
    </select>
</mapper>

MyBatis copie et colle directement le paramètre chaîne si vous utilisez le caractère $. D'autre part, il utilise la liaison de paramètre si vous utilisez le caractère #.

Vous devez ensuite exécuter votre SQL avec selectMap, selectList ou selectOne,

List<String> resultSet = sessionFactory.openSession().selectList("sql1.select1", pars);

Cet appel liera automatiquement les paramètres à l'instruction et l'exécutera.

ATTENTION:

<select id="select1" parameterType="map" resultType="String" >
    SELECT * FROM USERS
        WHERE 
        name LIKE #{name} AND num = #{number}
</select>

l'exécution peut échouer car MyBatis ne peut pas mapper plusieurs colonnes (SELECT *) ​​sur une seule chaîne (resultType = "String"). Deux corrections possibles de la requête sont présentées ci-dessous:

<!--Solution One-->
<select id="select1" parameterType="map" resultType="String" >
    SELECT name FROM USERS
        WHERE 
        name LIKE #{name} AND num = #{number}
</select>

<!--Solution Two-->
<select id="select1" parameterType="map" resultType="Java.util.LinkedHashMap" >
    SELECT * FROM USERS
        WHERE 
        name LIKE #{name} AND num = #{number}
</select>

Pour solution deux, vous devez exécuter la requête mybatis en utilisant le code Java ci-dessous:

List<Map<?, ?>> resultSet = sessionFactory.openSession().selectList("sql1.select1", pars);

Détails de Pourquoi getBoundSql renvoie une requête avec?:

La liaison des paramètres est effectuée au niveau du pilote afin que vous n'ayez pas une chaîne SQL comme celle-ci.

SELECT * FROM USERS
WHERE 
name LIKE 'john' AND num = 12345

Au lieu de cela, vous aurez un modèle de requête SQL qui est prêt pour la liaison de paramètres,

SELECT * FROM USERS
    WHERE 
    name LIKE ? AND num = ?

L'ajout de paramètres dans une chaîne sql autorise sql injection. La méthode la plus sûre consiste à utiliser la méthode de liaison de paramètre fournie avec SQL Driver et MyBatis utilise toujours la liaison de paramètre.

Supposons que vous ayez créé manuellement votre commande SQL en tant que chaîne et supposons que je sois un utilisateur malveillant en essayant d'accéder à vos données. je peux écrire 

john' or ''='

Donc, cela va générer la commande SQL ci-dessous:

SELECT * FROM USERS
WHERE 
name LIKE 'john' or ''='' AND num = 12345

Avantages supplémentaires de la liaison de paramètres

Le deuxième avantage de la liaison de paramètres est qu’elle permet des instructions préparées. Supposons que vous ayez besoin d'exécuter le même sql 1000 fois avec des paramètres différents. 

Si vous générez des chaînes SQL avec des paramètres liés,

SELECT * FROM USERS WHERE name LIKE 'john' AND num = 12345;
SELECT * FROM USERS WHERE name LIKE 'foo' AND num = 67890;

le serveur de base de données devra analyser chaque commande SQL une par une, puis les exécuter.

Avec des requêtes SQL paramétrées, 

SELECT * FROM USERS WHERE name LIKE ? AND num = ?

Le pilote SQL met en cache la requête. L'analyse est effectuée une seule fois, puis il lie différents paramètres à la commande same SQL.

Mise à jour: utilisation de BoundSql en dehors de MyBatis

Vous pouvez toujours utiliser le sql paramétré (boundSql) avec une autre bibliothèque ou Java.sql.Connection de Java. Ci-dessous un exemple:

Connection myConnection;
PreparedStatement preparedStatement = myConnection.prepareStatement(boundSql);
preparedStatement.setString(1, "john"); //First parameter starts with 1 not 0!
preparedStatement.setInt(2, 12345);
ResultSet results = preparedStatement.executeQuery();
8
vahapt
            SELECT(" * ");
            FROM(" student ");
            WHERE(" ten LIKE '%' #{ten} '%' ");

Vous pouvez l'utiliser et vous devez mettre un espace (_) entre '%' et # {}

0
Trang NT