Avoid quote (') when using INSERT in java

0

Good morning,

I am encountering a problem when performing the INSERT command in java. One of the fields is the name of the game, and being in English there are some that include a quote ('), that is why if for example the name of the game you have to enter is Tom Clancy's Rainbow Six, java is only me taking Tom Clancy, and the program stops running because of the following error: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 's Rainbow Six Siege'' at line 1 . That line corresponds to the line where I use INSERT .

The code I'm using:

public class Conectate {
private String driver ="com.mysql.jdbc.Driver";
private String cadenaConexion ="jdbc:mysql://localhost/XboxOne";
private String pass = "";
private String usuario = "root";
public Connection con;

//public Conectate(Map<String,  Map<String, Item>> gamesByCountry, Map<String, String> codesByTitle,Map<String, String> countries) {
public Conectate(ArrayList<Item> games) {    

    try {
        Class.forName(driver);
        con = DriverManager.getConnection(cadenaConexion, usuario, pass);
        System.out.println("¡Conectado!");


        //CREAMOS LA TABLA
        Statement st = con.createStatement();

        st.executeUpdate("CREATE TABLE IF NOT EXISTS info_XboxOne (id INT AUTO_INCREMENT, PRIMARY KEY(id), "
                + "Juego_vinculado VARCHAR(500), Juego VARCHAR(500), Tipologia VARCHAR (500), Pertenece VARCHAR (500), "
                + "Nota VARCHAR (10), Descripcion_Ingles TEXT(4000), Descripcion_Castellano TEXT(4000), Pegi VARCHAR(10), Descripcion_Pegi VARCHAR(200),"
                + "Lanzamiento VARCHAR (50))");

        System.out.println( "Tabla creada!");


        for (Item game : games) {

            String titulo = game.getName();
            ResultSet rs = st.executeQuery("SELECT * FROM info_XboxOne WHERE juego = '" + titulo + "'");

            if (!rs.next()) { //si se cumple esta condicción significa que el juego no está incluido, con lo que lo metemos
                PreparedStatement ps = con.prepareStatement("INSERT INTO info_XboxOne (Juego, Tipologia, Pertenece, "
                + "Nota, Descripcion_Ingles, Descripcion_Castellano, Pegi, Descripcion_Pegi"
                + ") VALUES (?,?,?,?"
                + ",?,?,?,?"
                + ")");

                ps.setString(1,game.getName());
                ps.setString(2,game.getValues().get(Constants.TIPOLOGIA));
                ps.setString(3,game.getValues().get(Constants.PERTENECE));                                            
                ps.setString(4,game.getValues().get(Constants.NOTA));
                ps.setString(5,game.getValues().get(Constants.DESCRIPCION_INGLES));
                ps.setString(6,game.getValues().get(Constants.DESCRIPCION_CASTELLANO));
                ps.setString(7,game.getValues().get(Constants.PEGI));
                ps.setString(8,game.getValues().get(Constants.DESCRIPCION_PEGI));    

                ps.executeUpdate();

            } else {
                String query = "UPDATE info_XboxOne SET Tipologia = ?, Pertenece = ?, "
                + "Nota = ?, Descripcion_Ingles = ?, Descripcion_Castellano = ?, "
                + "Pegi = ?, Descripcion_Pegi = ? WHERE juego = " + titulo;
                PreparedStatement ps = con.prepareStatement(query);

                ps.setString(2,game.getValues().get(Constants.TIPOLOGIA));
                ps.setString(3,game.getValues().get(Constants.PERTENECE));                                            
                ps.setString(4,game.getValues().get(Constants.NOTA));
                ps.setString(5,game.getValues().get(Constants.DESCRIPCION_INGLES));
                ps.setString(6,game.getValues().get(Constants.DESCRIPCION_CASTELLANO));
                ps.setString(7,game.getValues().get(Constants.PEGI));
                ps.setString(8,game.getValues().get(Constants.DESCRIPCION_PEGI));

                ps.executeUpdate();
            }           
        }

} catch (Exception e) {
            JOptionPane.showMessageDialog(null, "No se ha podido establecer la conexión con la DB" + e);
            e.printStackTrace();
        }

}

public String ConvertirObjectToString(Object Obj) {
String Str="";
if(Obj!=null){
    Str = Obj.toString();
}
return Str;
}  
}

Is there any way to prevent the name quotes from posing a problem for execution? It would also happen to me with another field, but this one that commented is the one that has skipped me first.

    
asked by JetLagFox 27.02.2017 в 23:23
source

4 answers

3

To avoid these single quote problems, it is important to use parameters with PreparedStatement s, instead of concatenating values in the SQL string directly. I see that you already do it correctly with your INSERT sentence. You still have to do it with your SELECT . Not only will it avoid this kind of problem, but it will also protect you from SQL injection attacks.

I take this opportunity to also recommend that you use the try-with-resources pattern at the time of handle objects of PreparedStatement and / or ResultSet to avoid keeping resources open longer than necessary.

So, instead of:

ResultSet rs = st.executeQuery("SELECT * FROM info_XboxOne WHERE juego = '" + titulo + "'");

// usar rs...

The correct way to do it would be:

try (PreparedStatement ps = con.prepareStatement("SELECT * FROM info_XboxOne WHERE juego = ?")) {
    ps.setString(1, titulo);

    try (ResultSet rs = ps.executeQuery()) {
        // usar rs...
    }
}

Edit

Here is a more complete example that applies to your case. I also take advantage to correct your UPDATE that suffers from the same problem as your SELECT , and also did not number your parameters correctly:

for (Item game : games) {
    String titulo = game.getName();

    boolean isInsert;
    try (PreparedStatement ps = con.prepareStatement("SELECT * FROM info_XboxOne WHERE juego = ?")) {
        ps.setString(1, titulo);

        try (ResultSet rs = ps.executeQuery()) {
            isInsert = !rs.next();
        }
    }

    if (isInsert) { //si se cumple esta condicción significa que el juego no está incluido, con lo que lo metemos
        try(PreparedStatement ps = con.prepareStatement("INSERT INTO info_XboxOne (Juego, Tipologia, Pertenece, "
            + "Nota, Descripcion_Ingles, Descripcion_Castellano, Pegi, Descripcion_Pegi"
            + ") VALUES (?,?,?,?,?,?,?,?)")) {

            ps.setString(1,titulo);
            ps.setString(2,game.getValues().get(Constants.TIPOLOGIA));
            ps.setString(3,game.getValues().get(Constants.PERTENECE));                                            
            ps.setString(4,game.getValues().get(Constants.NOTA));
            ps.setString(5,game.getValues().get(Constants.DESCRIPCION_INGLES));
            ps.setString(6,game.getValues().get(Constants.DESCRIPCION_CASTELLANO));
            ps.setString(7,game.getValues().get(Constants.PEGI));
            ps.setString(8,game.getValues().get(Constants.DESCRIPCION_PEGI));    

            ps.executeUpdate();
        }
    } else {
        String query = "UPDATE info_XboxOne SET Tipologia = ?, Pertenece = ?, "
        + "Nota = ?, Descripcion_Ingles = ?, Descripcion_Castellano = ?, "
        + "Pegi = ?, Descripcion_Pegi = ? WHERE juego = ?";

        try (PreparedStatement ps = con.prepareStatement(query)) {
            ps.setString(1,game.getValues().get(Constants.TIPOLOGIA));
            ps.setString(2,game.getValues().get(Constants.PERTENECE));                                            
            ps.setString(3,game.getValues().get(Constants.NOTA));
            ps.setString(4,game.getValues().get(Constants.DESCRIPCION_INGLES));
            ps.setString(5,game.getValues().get(Constants.DESCRIPCION_CASTELLANO));
            ps.setString(6,game.getValues().get(Constants.PEGI));
            ps.setString(7,game.getValues().get(Constants.DESCRIPCION_PEGI));
            ps.setString(8,titulo);

            ps.executeUpdate();
        }
    }           
}
    
answered by 28.02.2017 в 16:19
0

Use Hibernate or JPA failing. It is much more efficient and the chances of a hacker doing SQLInjection are much lower compared to the code you are implementing.

Some reference links:

Hibernate How-To JPA How-To

Finally, it is not a good practice to modify the data model from your source code, speaking from a design and software maintenance aspect.

    
answered by 28.02.2017 в 16:03
0

I solved it using \" instead of the single quotes:

ResultSet rs = st.executeQuery("SELECT * FROM info_XboxOne WHERE juego = \"" + titulo + "\"");
    
answered by 28.02.2017 в 01:00
0

Good morning.

For this type of case I would recommend you to use the PreparedStatement , besides that you avoid making the use of quotes (since the values are passed through parameters), with the Select are much more secure and avoid the SQL code injection in your query, as discussed above.

Regarding hibernate or JPA , if you need inter-database portability (easily switch from one database to another), if it is recommended, in addition to ORM they have points against, among them: the speed and load of objects that it generates, since in an ORM all the tables that it generates are objects.

By this I do not mean that Hibernate or JPA do not work, only that its use depends on your needs.

I would use them in systems that require database portability or that the workload is not so demanding (management systems for example). These frameworks of BD can be optimized in terms of speed, for example hibernate uses a cache to know with what objects you try, save or update and store them there to have them available the next time you need them, but beware, they only stay for a time and then the framework discards them.

I leave a link for you to see an example of the PrepareStatement. PrepareStatement Example

    
answered by 28.02.2017 в 16:34