Java
JDBC
JDBC API
obsahuje třídu nazvanou
PreparedStatement
,
která programátorovi umožňuje bezpečně vkládat uživatel zadaná
data do SQL příkazu. Umístění každé vstupní hodnoty v dotazu
označuje otazníček. Poté se k bezpečnému vložení hodnoty používají
rozličné metody set*()
.
String name = //uživatelský vstup
int age = //uživatelský vstup
Connection connection = DriverManager.getConnection(...);
PreparedStatement statement = connection.prepareStatement(
"SELECT * FROM people WHERE lastName = ? AND age > ?" );
statement.setString(1, name); //lastName je VARCHAR
statement.setInt(2, age); //age je INT
ResultSet rs = statement.executeQuery();
while (rs.next()){
//...
}
Jakmile je vytvořen objekt PreparedStatement
, lze ho opakovaně použít
pro více příkazů (například při použití stejného příkazu pro aktualizaci
více řádků tabulky). Tyto objekty však nejsou thread-safe, kvůli
tomu, že se nastavování parametrů a provádění příkazů provádí mnoha
voláními metod. Proto byste měli objekty PreparedStatement
definovat
jen na úrovni metod (nikoli na úrovni tříd), abyste se vyhli problémům
s paralelismem.
List<Person>; people = //uživatelský vstup
Connection connection = DriverManager.getConnection(...);
connection.setAutoCommit(false);
try {
PreparedStatement statement = connection.prepareStatement(
"UPDATE people SET lastName = ?, age = ? WHERE id = ?");
for (Person person : people){
statement.setString(1, person.getLastName());
statement.setInt(2, person.getAge());
statement.setInt(3, person.getId());
statement.execute();
}
connection.commit();
} catch (SQLException e) {
connection.rollback();
}
Více informací o PreparedStatement
se nachází v
tutoriálu JDBC od Oraclu.
Hibernate
Hibernate používá pro bezpečné vkládání dat do příkazu pojmenované parametry. Pojmenovaný parametr sestává z dvojtečky následované jedinečným jménem parametru.
String name = //uživatelský vstup
int age = //uživatelský vstup
Session session = //...
Query query = session.createQuery("from People where lastName = :name and age > :age");
query.setString("name", name);
query.setInteger("age", age);
Iterator people = query.iterate();
I Hibernate podporuje poziční parametry jako PreparedStatement
,
ale preferují se pojmenované parametrym protože výsledný příkaz
je s nimi o něco lépe čitelný.
Více informací o pojmenovaných parametrech najdete v příručce Hibernate.
MyBatis
MyBatis je databázový framework, který programátora odstiňuje od spousty JDBC kódu, čímž mu/jí umožňuje soustředit se na psaní SQL. SQL příkazy se typicky ukládají do XML souborů.
V pozadí MyBatis automaticky vytváří instance PreparedStatement
.
Programátor se nemusí o nic dalšího starat.
Pro představu je zde příklad volání jednoduchého dotazu pomocí
MyBatis. Vstupní data se předávají do instance PeopleMapper
a poté se vloží do dotazu selectPeopleByNameAndAge
.
XML dokument s mapováním
<?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="com.bobbytables.mybatis.PeopleMapper">
<select id="selectPeopleByNameAndAge" resultType="list">
<!-- lastName a age jsou automaticky ošetřeny --->
SELECT * FROM people WHERE lastName = #{lastName} AND age > #{age}
</select>
</mapper>
Mapující třída
public interface PeopleMapper {
List<Person> selectPeopleByNameAndAge(@Param("lastName") String name, @Param("age") int age);
}
Provedení dotazu
String name = //uživatelský vstup
int age = //uživatelský vstup
SqlSessionFactory sqlMapper = //...
SqlSession session = sqlMapper.openSession();
try {
PeopleMapper mapper = session.getMapper(PeopleMapper.class);
List<Person> people = mapper.selectPeopleByNameAndAge(name, age); //data se automaticky ošetří
for (Person person : people) {
//...
}
} finally {
session.close();
}