This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 6 years ago.
Here is the connection class
public class ConnectionManager {
Connection cn = null;
public Connection getConnection() throws ClassNotFoundException, SQLException {
String dbPath = "jdbc:mysql://localhost:3306/postjob";
String username = "root";
String password = "root";
Class.forName("com.mysql.jdbc.Driver");
cn = DriverManager.getConnection(dbPath, username, password);
return cn;
}
public void closeConnection() throws SQLException{
cn.close();
}
}
Here is my service class
public class UserdetailsServices {
public Connection connection;
public ResultSet resultset;
// private Object resultSet;
public UserdetailsServices() {
try {
connection = new ConnectionManager().getConnection();
//here I am getting connection=null.
} catch (ClassNotFoundException ex) {
Logger.getLogger(UserdetailsServices.class.getName()).log(Level.SEVERE, null, ex);
} catch (SQLException ex) {
Logger.getLogger(UserdetailsServices.class.getName()).log(Level.SEVERE, null, ex);
}
}
/**
*
* #param user
* #return
*/
public boolean registerUser(UserModal user) {
try {
java.sql.PreparedStatement psmt = connection.prepareStatement("insert into userdetails(role,name,gender,email,password,cpassword,contact) values(?,?,?,?,?,?,?)");
psmt.setString(1, user.getRole());
psmt.setString(2, user.getName());
psmt.setString(3, user.getGender());
psmt.setString(4, user.getEmail());
psmt.setString(5, user.getPassword());
psmt.setString(6, user.getCpassword());
psmt.setString(6, user.getContact());
int flag = psmt.executeUpdate();
if (flag > 0) {
return true;
} else {
return false;
}
} catch (SQLException ex) {
return false;
}
}
Insert have 7 fields but preparaedstatement is setting only 6 fields. It is missing setting contact value. That's why it is giving null error.
Instead of this
psmt.setString(6, user.getCpassword());
psmt.setString(6, user.getContact());
use this
psmt.setString(6, user.getCpassword());
psmt.setString(7, user.getContact());
Related
There are two methods in which the PreparedStatement is used.
The first method is called in the second method.
First method:
protected List<String> findResultsByMandantId(Long mandantId) {
List<String> resultIds = new ArrayList<>();
ResultSet rs;
String sql = "SELECT result_id FROM results WHERE mandant_id = ?";
PreparedStatement statement = getPreparedStatement(sql, false);
try {
statement.setLong(1, mandantId);
statement.execute();
rs = statement.getResultSet();
while (rs.next()) {
resultIds.add(rs.getString(1));
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
return resultIds;
}
Second method:
protected void findResultLineEntityToDelete(Long mandantId, String title, String context) {
List<String> resultIds = findResultsByMandantId(mandantId);
String [] resultIdsArr = resultIds.toArray(String[]::new);
ResultSet rs;
//String sql = "SELECT * FROM resultline WHERE result_id in (SELECT result_id FROM results WHERE mandant_id =" + mandantId + ")";
String sql = "SELECT * FROM resultline WHERE result_id in (" + String.join(", ", resultIdsArr)+ ")";
PreparedStatement statement = getPreparedStatement(sql, false);
try {
statement.execute();
rs = statement.getResultSet();
while (rs.next()) {
if (rs.getString(3).equals(title) && rs.getString(4).equals(context)) {
System.out.println("Titel: " + rs.getString(3) + " " + "Context: " + rs.getString(4));
}
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
The class in which both methods are located extends the JDBCBaseManager.
JDBCBaseManager:
private final String url = "jdbc:mysql://localhost:3306/database";
private final String userName = "root";
private final String password = "";
private Connection connection = null;
private PreparedStatement preparedStatement = null;
private int batchSize = 0;
public JDBCBaseManager() {
// Dotenv env = Dotenv.configure().directory("./serverless").load();
// url = env.get("DB_PROD_URL");
// userName = env.get("DB_USER");
// password = env.get("DB_PW");
}
public void getConnection() {
try {
if (connection == null) {
connection = DriverManager.getConnection(url, userName, password);
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public PreparedStatement getPreparedStatement(String sql, boolean returnGeneratedKeys) {
try {
if (connection == null) {
getConnection();
}
if (preparedStatement == null) {
if (!returnGeneratedKeys) {
preparedStatement = connection.prepareStatement(sql);
} else {
preparedStatement = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
connection.setAutoCommit(false);
}
}
return preparedStatement;
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public void closeConnection() {
try {
if (connection != null && !connection.isClosed()) {
System.out.println("Closing Database Connection");
connection.close();
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public void startBatch(int batchSize) throws SQLException {
connection.setAutoCommit(false);
setBatchSize(batchSize);
}
public void commit() {
try {
if (connection != null && !connection.isClosed()) {
connection.commit();
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public int getBatchSize() {
return batchSize;
}
public void setBatchSize(int batchSize) {
this.batchSize = batchSize;
}
The ResultSet in the second method still contains the results from the first method.
I already tried to close the connection and open it again before the second method is executed, but then I get the errors:
java.sql.SQLException: No operations allowed after statement closed.
java.sql.SQLNonTransientConnectionException: No operations allowed
after connection closed.
Can you tell me how to deal with the statement correctly in this case? Is my BaseManager incorrectly structured?
Here lies the error
public JDBCBaseManager() {
private PreparedStatement preparedStatement = null;
public PreparedStatement getPreparedStatement(String sql, boolean returnGeneratedKeys) {
try {
......
if (preparedStatement == null) {
if (!returnGeneratedKeys) {
preparedStatement = connection.prepareStatement(sql);
} else {
preparedStatement = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
connection.setAutoCommit(false);
}
}
return preparedStatement;
You build the prepare statement only the first time the method getPreparedStatement is called because only the first time the field preparedStatement is null. Every next time you call the method getPreparedStatement you receive the previous preparedStatement from the previous SQL and not the new one.
Remove the check for if (preparedStatement == null) {
You need to build a new preparedStatement every time you want to execute a new SQL.
To get an idea of what the basic structure looks like, I downloaded a money system including MySQL from Spigot and looked at the code.
public static boolean playerExists(String uuid) {
try {
ResultSet rs = Simplecoinsystem.mysql.query("SELECT * FROM CoinData WHERE UUID= '" + uuid + "'");
if (rs.next())
return (rs.getString("UUID") != null);
return false;
} catch (SQLException e) {
e.printStackTrace();
return false;
}
}
public static void createPlayer(String uuid) {
if (!playerExists(uuid))
Simplecoinsystem.mysql.update("INSERT INTO CoinData (UUID, COINS) VALUES ('" + uuid +
"', '" + Simplecoinsystem.getInstance().getConfig().getInt("startcoins") + "');");
}
public static Integer getCoins(String uuid) {
Integer i = Integer.valueOf(0);
if (playerExists(uuid)) {
try {
ResultSet rs = Simplecoinsystem.mysql.query("SELECT * FROM CoinData WHERE UUID= '" + uuid + "'");
if (rs.next())
Integer.valueOf(rs.getInt("COINS"));
i = Integer.valueOf(rs.getInt("COINS"));
} catch (SQLException e) {
e.printStackTrace();
}
} else {
createPlayer(uuid);
}
return i;
}
public static void setCoins(String uuid, Integer coins) {
if (playerExists(uuid)) {
Simplecoinsystem.mysql.update("UPDATE CoinData SET COINS= '" + coins + "' WHERE UUID= '" + uuid + "';");
} else {
createPlayer(uuid);
}
}
Am I correct that it is actually impractical to create a new entry with the uuid of the non-existent player after each query of the coins if the player does not exist?
Wouldn't this make it possible to flood the database with thousands of unnecessary entries by issuing, for example, a "/money (player)" command as an evil player/admin?
Couldn't I just ask when entering the server if the uuid is already stored and if not, just enter it? This way there would only be entries from players who have already been on the server before. Whether this needs great server performance, I'm not sure.
This is my first own MySQL class.
public class MySQL {
private String host, database, user, password;
private int port;
private Connection con;
public MySQL(String host, int port, String database, String user, String password) {
this.host = host;
this.port = port;
this.database = database;
this.user = user;
this.password = password;
connect();
}
public void connect() {
try {
con = DriverManager.getConnection("jdbc:mysql://" + host + ":" + port + "/" + database + "?autoReconnect=true", user, password);
System.out.println("&cDie MySQL Verbindung wurde erfolgreich aufgebaut!");
} catch (SQLException e) {
e.printStackTrace();
}
}
public void disconnect() {
try {
if(this.con != null) {
this.con.close();
System.out.println("§cDie MySQL Verbindung wurde erfolgreich beendet!");
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void update(String query) {
try {
Statement st = con.createStatement();
st.executeUpdate(query);
st.close();
} catch (Exception e) {
e.printStackTrace();
connect();
}
}
public ResultSet qry(String query) {
ResultSet rs = null;
try {
Statement st = con.createStatement();
rs = st.executeQuery(query);
} catch (Exception e) {
e.printStackTrace();
connect();
}
return rs;
}
public Connection getConnection() {
return this.con;
}
}
Except for this part, both MySQL classes are built relatively the same.
This is the part that is in the MySQL class of the Spigot plugin.
Your code have multiple issues.
When the connection will be closed, next time you will have an error. In your Mysql class, I suggest you to do:
public Connection getConnection() {
if(con == null || con.isClosed())
connect();
return con;
}
Then, use it in all method like getConnection().prepareStatement().
You can be attacked with SQL Injection. To fix this, try to do something like:
PreparedStatement st = con.prepareStatement("SELECT * FROM CoinData WHERE UUID = ?");
st.setString(1, uuid.toString()); // Yes it start at 1 !!
st.executeUpdate();
With this, even with all values, you can't be attacked with injections.
You will have an error while getting coins:
if (rs.next()) // go to good line
Integer.valueOf(rs.getInt("COINS")); // useless convertion
i = Integer.valueOf(rs.getInt("COINS")); // error if no line.
You can just do:
if(rs.next())
i = rs.getInt("COINS");
If the column "UUID" is unique, you will not have duplicated lines.
Finally, about performance, it's better to do it one time: at login, instead of all time. You can also create an object stored in an hashmap to easier access to it, without using SQL, like that:
public static HashMap<UUID, Integer> coinsByPlayer = new HashMap<>();
OR:
public static HashMap<UUID, MyObject> coinsByPlayer = new HashMap<>();
public class MyObject {
private int coins = 0;
public MyObject(UUID uuid) {
// make SQL request to get data
}
public int getCoins() {
return coins;
}
public void setCoins(int next){
coins = next;
// here make "UPDATE" sql query
}
}
What do you say? Is it ok with the try/catch function? #Elikill58
public Connection getConnection() {
try {
if(con == null || con.isClosed()) {
connect();
}
} catch (SQLException e) {
e.printStackTrace();
}
return con;
}
edit:
public Connection getConnection_one() throws SQLException {
if(con == null || con.isClosed()) {
connect();
return con;
} else {
return con;
}
}
I connect to Hive and get id's of my data from row of table. Problems does not happens, when I connect to hive, send request and get response. But when i get id's from ResultSet i get an exception: org.apache.thrift.transport.TTransportException: SASL authentication not complete. Why does this exception arise and what needs to be done to avoid it? Sorry for my bad english.
It's my subsidiary class to create hive connection and send requests:
public class HiveDataSearcher implements AutoCloseable {
private static final String hiveDriverName = "org.apache.hive.jdbc.HiveDriver";
static {
try {
Class.forName(hiveDriverName);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
private Connection hiveConnection;
private String tableName;
private String whereBody;
public HiveDataSearcher(String url, String login, String password) {
try {
hiveConnection = DriverManager.getConnection(url, login, password);
} catch (SQLException e) {
throw new RuntimeException(e);
}
this.tableName = "";
this.whereBody = "";
}
public HiveDataSearcher(Connection hiveConnection) {
Objects.requireNonNull(hiveConnection, "hiveConnection");
this.hiveConnection = hiveConnection;
this.tableName = "";
this.whereBody = "";
}
public String getTableName() {
return tableName;
}
public HiveDataSearcher setTableName(String tableName) {
Objects.requireNonNull(tableName, "tableName");
this.tableName = tableName;
return this;
}
public String getWhereBody() {
return whereBody;
}
public HiveDataSearcher setWhereBody(String whereBody) {
Objects.requireNonNull(whereBody, "whereBody");
this.whereBody = whereBody;
return this;
}
public ResultSet select(String ... selectParams) {
return select(Arrays.asList(selectParams));
}
public ResultSet select(Iterable<String> selectParams) {
String request = prepareRequest(selectParams);
ResultSet response;
try {
response = hiveConnection
.createStatement()
.executeQuery(request);
} catch (SQLException e) {
throw new RuntimeException(e);
}
return response;
}
private String prepareRequest(Iterable<String> selectParams) {
return new StringBuilder()
.append("select").append(' ').append(selectParamsToHiveFormat(selectParams)).append(' ')
.append("from").append(' ').append(tableName).append(' ')
.append("where").append(' ').append(whereBody)
.toString();
}
private String selectParamsToHiveFormat(Iterable<String> selectParams) {
StringBuilder formattedSelectParams = new StringBuilder();
for (String selectedParam : selectParams) {
formattedSelectParams.append('\'').append(selectedParam).append('\'').append(',');
}
if (formattedSelectParams.length() == 0) {
formattedSelectParams.append('*');
} else {
formattedSelectParams.deleteCharAt(formattedSelectParams.length() - 1);
}
return formattedSelectParams.toString();
}
public void close() {
if (hiveConnection != null) {
try {
hiveConnection.close();
} catch (SQLException e) {
//nothing to do, just close connection
} finally {
hiveConnection = null;
}
}
}
}
This is the code in which i connect to hive:
private static final String HIVE_URL = <hive url>;
private static final String HIVE_LOGIN = <hive login>;
private static final String HIVE_PASSWORD = <hive password>;
private static final String[] SEARCH_FIELDS = new String[] {"rowkey"};
private List<String> getIdsFromHive(String tableName, String whereBody) {
ResultSet hiveResponse;
try (HiveDataSearcher searcher = new HiveDataSearcher(HIVE_URL, HIVE_LOGIN, HIVE_PASSWORD)) {
hiveResponse = searcher
.setTableName(tableName)
.setWhereBody(whereBody)
.select(SEARCH_FIELDS);
}
List<String> ids = new ArrayList<>();
try {
while (hiveResponse.next()) { // in this place throw TTransportException
ids.add(hiveResponse.getString(SEARCH_FIELDS[0]));
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
return ids;
}
In my case, the reason for this exception is closed the connection before closed the statement. So I suggest you to check whether you has maintain the connection correctly.
Here is my code, wish it will inspire you something:
Wrong code, close connection before closing the statement:
Connection connection = null;
Statement statement = null;
try {
connection = HIVEUTILS.getConnection();
statement = connection.createStatement();
statement.execute("DROP TABLE IF EXISTS tbl1");
statement.execute("CREATE TABLE `tbl1` (`id` int)");
statement.execute("INSERT INTO tbl1 VALUES(1)");
}finally {
if (connection != null){
connection.close();
}
if (statement != null){
statement.close(); // exception occur here.
}
}
The correct order of closing is: close resultSet(if any) -> close statement -> close connection.
Connection connection = null;
Statement statement = null;
try {
connection = HIVEUTILS.getConnection();
statement = connection.createStatement();
statement.execute("DROP TABLE IF EXISTS tbl1");
statement.execute("CREATE TABLE `tbl1` (`id` int)");
statement.execute("INSERT INTO tbl1 VALUES(1)");
}finally {
if (statement != null){
statement.close(); // change the order
}
if (connection != null){
connection.close();
}
}
This question already has answers here:
Multiple returns: Which one sets the final return value?
(7 answers)
Closed 5 years ago.
I have a database and it has a table user which consists of many attributes like name ,email,etc. Also it has username and password in VARCHAR datatype. I wrote two classes LoginModel and Controller. controller has method loginit through which it checks if login method from LoginModel returns true or not. I am not able to find out why LoginModel always returns false. Please help.
Here are my methods :
from class LoginModel
public boolean login(String userid, String userpass) throws SQLException {
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
String query = "SELECT * FROM user WHERE username = ? AND password = ?";
try{
preparedStatement = connection.prepareStatement(query);
preparedStatement.setString(1,userid);
preparedStatement.setString(2,userpass);
resultSet = preparedStatement.executeQuery();
if(resultSet.next()){
return true;
}
else {
// System.out.println(resultSet.next());
return false;
}
}
catch (Exception e){
return false;
}
finally {
preparedStatement.close();
resultSet.close();
return false;
}
}
from class Controller
public void loginit() throws SQLException {
String userid = uid.getText();
String userpass = upass.getText();
try {
if (loginmodel.login(userid, userpass)) {
lblstatus.setText("YES");
}
else
lblstatus.setText("Invalid");
} catch (SQLException e) {
lblstatus.setText("No");
e.printStackTrace();
}
}
It is a JavaFX application. userid and userpass are ids of text-field and password-field respectively. lblstatus is label which always shows Invalid, can't figure out why!
Here is snapshot of my database
remove return false from the finally block. It will executed in case of execption and in case you get no exception.
finally {
preparedStatement.close();
resultSet.close();
return false;
}
Change your code to:
public boolean login(String userid, String userpass) throws SQLException {
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
String query = "SELECT * FROM user WHERE username = ? AND password = ?";
try{
preparedStatement = connection.prepareStatement(query);
preparedStatement.setString(1,userid);
preparedStatement.setString(2,userpass);
resultSet = preparedStatement.executeQuery();
if(resultSet.next()){
return true;
}
else {
// System.out.println(resultSet.next());
return false;
}
}
catch (Exception e){
return false;
}
finally {
preparedStatement.close();
resultSet.close();
}
return false;
}
public class BancoDeDados {
static String url = "jdbc:mysql://localhost:3306/Estoque";
static String pass = "admin";
static String user = "admin";
static Connection conexao = null;
public static boolean conecta() throws ClassNotFoundException {
try {
Class.forName("mysql.Driver");
conexao = DriverManager.getConnection(url, user, pass);
//System.out.println("Conectado.");
JOptionPane.showMessageDialog(null, "Conectado com Sucesso!");
return true;
} catch (SQLException e) {
JOptionPane.showMessageDialog(null, "Usuário e/ou senha estão incorretos!");
//System.out.println("Usuário e/ou senha estão errados.");
return false;
}
}
public class TelaPrincipal extends JFrame {
Connection conexao = null;
PreparedStatement pst = null;
ResultSet rs = null;
private JPanel contentPane;
private JTextField textLogin;
private JPasswordField textSenha;
public void logar(){
String sql = "Select *from Login WHERE Usuario = ? and senha = ?";
try{
pst = conexao.prepareStatement(sql);
pst.setString(1, textLogin.getText());
pst.setString(2, textSenha.getText());
rs = pst.executeQuery();
if(rs.next()){
TelaOpcoes telaopcoes = new TelaOpcoes();
telaopcoes.setVisible(true);
dispose();
}
else{
JOptionPane.showMessageDialog(null, "Usuário e Senha Inválidos");
}
}
catch(SQLException error){
JOptionPane.showMessageDialog(null, error);
}
}
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
TelaPrincipal frame = new TelaPrincipal();
frame.setVisible(true);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public TelaPrincipal() throws ClassNotFoundException {
conexao = BancoDeDados.conecta();
this.setLocationRelativeTo(null);
Its doing error on penultimate line " CONEXAO = BANCODEDADOS.CONECTA(); " saying that "Type mismatch : cannot convert from boolean to Connection"
Can somebody help me please? thanks!
CONEXAO = BANCODEDADOS.CONECTA();
Here CONEXAO is a connection variable
but the method
BANCODEDADOS.CONECTA(); returns a boolean value.
so change the type of variable CONEXAO
or create a new variable boolean type for store the result
Boolean conexao = BancoDeDados.conecta();
Your method returns a boolean (not a Connection). Change
public static boolean conecta() throws ClassNotFoundException {
try {
Class.forName("mysql.Driver");
conexao = DriverManager.getConnection(url, user, pass);
//System.out.println("Conectado.");
JOptionPane.showMessageDialog(null, "Conectado com Sucesso!");
return true;
} catch (SQLException e) {
JOptionPane.showMessageDialog(null, "Usuário e/ou senha estão incorretos!");
//System.out.println("Usuário e/ou senha estão errados.");
return false;
}
}
to something like
public static Connection conecta() {
Connection conn = null;
try {
Class.forName("mysql.Driver");
conn = DriverManager.getConnection(url, user, pass);
} catch (Exception e) {
e.printStackTrace();
}
return conn;
}
You are returning boolean from method conecta() and in constructor you are storing it to java.sql.Connection...
So change the return type of conecta() method to java.sql.Connection..
conexao is object of Connection and you are assigning value of method call BancoDeDados.conecta();[Which return boolean] to Connection.
Change your code like
Boolean result = BancoDeDados.conecta();
Or return conexao from method conecta to support your code.
Edit:
Driver to connect MySQL is com.mysql.jdbc.Driver. Change your code
Class.forName("mysql.Driver");
to
Class.forName("com.mysql.jdbc.Driver");