1

I have been trying to insert some variables into a MySQL database, but it doesn't seem to be working. When I type the value directly into the query it works, but this is obviously not very helpful. I have typed my code below along with the erorr message, I just don't know how I can change my code to make it work. Any help you can provide would be most helpful! Please note the function is called selectCountry instead of something like insertCountry, please ignore this.

import java.sql.*;

public class Database_Interactor {
    public static Connection letConnect()  {
        Connection conn =null;
        String url,username,password = null;
        url="jdbc:mysql://localhost:3306/DatabaseName";
        username = "username";
        password = "password";
        
        try {Class.forName("com.mysql.cj.jdbc.Driver");
            conn = DriverManager.getConnection(url,username,password);
        } catch (SQLException | ClassNotFoundException e) {
            e.printStackTrace();}
        return conn;}
    
    
    void SelectCountry(String country, String color, int X, int Y) {
        Connection conn = letConnect();
        try {
            Statement stmt = conn.createStatement();
            stmt.executeUpdate("INSERT INTO Country (CountryName, Color, XPosition, YPosition)\r\n"
                    + "VALUES (country,color,X,Y);");
            System.out.println("Inserted");
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

java.sql.SQLSyntaxErrorException: Unknown column 'country' in 'field list'
    at mysql.connector.java@8.0.30/com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:120)
    at mysql.connector.java@8.0.30/com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
    at mysql.connector.java@8.0.30/com.mysql.cj.jdbc.StatementImpl.executeUpdateInternal(StatementImpl.java:1334)
    at mysql.connector.java@8.0.30/com.mysql.cj.jdbc.StatementImpl.executeLargeUpdate(StatementImpl.java:2084)
    at mysql.connector.java@8.0.30/com.mysql.cj.jdbc.StatementImpl.executeUpdate(StatementImpl.java:1245)
    at Database_Interactor.SelectCountry(Database_Interactor.java:22)
    at MainClass.main(MainClass.java:8)

2 Answers2

8

Your method is not performing a select, it's performing an insert. So I would rename it. Java convention has methods start with a lowercase letter.

You should be using a PreparedStatement and binding the variables for your query1. And you aren't closing anything which is likely to leak cursors; I would use a try-with-Resources2. Something like this:

void insertCountry(String country, String color, int x, int y) {
    String sql = "INSERT INTO Country (CountryName, Color, XPosition, YPosition) "
            + "VALUES (?, ?, ?, ?)";
    try (Connection conn = letConnect();
            PreparedStatement ps = conn.prepareStatement(sql)) {
        ps.setString(1, country);
        ps.setString(2, color);
        ps.setInt(3, x);
        ps.setInt(4, y);
        ps.executeUpdate();
        System.out.println("Inserted");
    } catch (SQLException e) {
        e.printStackTrace();
    }
}

1This is also how you avoid SQL Injection attacks. See also, xkcd 327: Exploits of a Mom.
2A connection pool (for example HikariCP or others) would likely improve performance if your application will run for an extended period by amortizing the database connection time.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249
  • 4
    Note: Would help to use connection pooling here as establishing a connection for every query can be brutally slow depending on the server's configuration and/or network topology issues, but that's outside the scope of this particular question. – tadman Aug 18 '22 at 00:22
-4

After thinking about it for a little while, I edited my code and came up with somewhat a good solution to this problem, the code is below:

void insertCountry(String country, String color, int X, int Y) {
        Connection conn = letConnect();
        try {
            String sql = "INSERT INTO Country (CountryName, Color, XPosition, YPosition) VALUES ('"+country+"','"+color+"','"+X+"','"+Y+"');";
            System.out.println(sql);
            Statement stmt = conn.createStatement();
            stmt.executeUpdate(sql);
            System.out.println("Inserted");
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
  • 1
    Are you serious? There is an answer by @elliot which shows the correct way to do this. – Scary Wombat Aug 18 '22 at 01:42
  • I know, but after looking at his and then mine, the one I came up with seems much cleaner. At the beginning I thought I needed help with this, but it appears that I just needed to think about it some more. But hey, hopefully this discussion will help somebody out there. – Brandon Thies Aug 18 '22 at 02:15
  • 4
    @Brandon SQL Injection attacks are very real. I call this method. I provide `country` input of `Mexico'); DROP TABLE Country; --` and suddenly all of the countries are gone. – Elliott Frisch Aug 18 '22 at 02:53
  • 2
    for university group projects or something that is not of high consequences/risk, it is still fine (but not advisable) to do the above, but for anything that may be pushed out as a product, this would never get past any internal reviews – Tan Yu Hau Sean Aug 18 '22 at 03:02
  • 1
    This Answer neglectfully omits try-with-resources syntax to automatically close the database resources regardless of success or failure. In contrast, see [the correct Answer](https://stackoverflow.com/a/73396061/642706). – Basil Bourque Aug 18 '22 at 05:31
  • Hi Elliott, thank you for you input. I wasn't thinking of how it could be attacked (still a newbie here) I will be sure to use your solution, thanks again! – Brandon Thies Aug 18 '22 at 13:24
  • 1
    yeah, check out bobby tables, https://bobby-tables.com/ – Hi computer Aug 23 '22 at 06:17