Check existing entry in database + auto increment id -> multiple conditions - java

I'm creating a GUI application with an user form to generate a sheet, those sheets are saved in the H2 database, as for the user form I enter manually the sheet number in a textfield and the date from a datepicker.
Every sheet has its ID which shall be unique for that month. The first created sheet for that month has id 1, and 2nd is 2 and so on but for the next month the ID should restart from 1.
I need to check if the entry already exists in the database with that sheet number in that month. I created another column in the database where the number+month+year I extract from the textfields are stored and I check it there, but I am looking for another method without having to create the extra column.
Here are the setter and getters (I pasted only the 3 values):
public class FiseDetails {
private final IntegerProperty sheetNumber;
private final ObjectProperty<Date> sheetDate;
private final StringProperty numberAndDate;
public FiseDetails(Integer sheetNumber, Date sheetDate, String numberAndDate) {
this.sheetNumber = new SimpleIntegerProperty(sheetNumber);
this.sheetDate = new SimpleObjectProperty<>(sheetDate);
this.numberAndDate = new SimpleStringProperty(numberAndDate);
}
public Integer getSheetNumber() {
return sheetNumber.get();
}
public void setSheetNumber(Integer value) {
sheetNumber.set(value);
}
public IntegerProperty SheetNumberProperty() {
return sheetNumber;
}
public Date getSheetDate() {
return sheetDate.get();
}
public void setSheetDate(Date value) {
sheetDate.set(value);
}
public ObjectProperty SheetDateProperty() {
return sheetDate;
}
public String getNumberAndDate() {
return numberAndDate.get();
}
public void setNumberAndDate(String value) {
numberAndDate.set(value);
}
public StringProperty NumberAndDateProperty() {
return numberAndDate;
}
}
Here is part of the controller:
public class StartGUIController implements Initializable {
Connection conn = DbConnection.Connect();
ObservableList<FiseDetails> data = FXCollections.observableArrayList();
PreparedStatement preparedStatement = null;
ResultSet rs = null;
#FXML
private TextField txt_SheetNumber;
#FXML
private DatePicker sheetDate;
#FXML
void generateSheet(ActionEvent event) throws SQLException {
Integer id = Integer.parseInt(txt_SheetNumber.getText());
LocalDate selectedDate = sheetDate.getValue();
Date date = Date.valueOf(selectedDate);
LocalDate strgDate = sheetDate.getValue();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM- yyyy");
String formatedDate = (strgDate).format(formatter);
String last7 = formatedDate.substring(formatedDate.length() - 7);
String numberAndDate = txt_SheetNumber.getText() + " " + last7;
try (PreparedStatement checkNumberAndDateExists = conn.prepareStatement("SELECT 1 FROM SHEETSDB WHERE NUMBERANDDATE = ?")) {
checkNumberAndDateExists.setString(1, numberAndDate);
try (ResultSet result = checkNumberAndDateExists.executeQuery()) {
if (result.next()) {
Alert confirmation = new Alert(AlertType.INFORMATION);
confirmation.setTitle("Fisa existenta");
confirmation.setHeaderText(null);
confirmation.setContentText("Fisa " + txt_SheetNumber.getText() + "/" + sheetDate.getValue() + " exista");
confirmation.showAndWait();
} else {
String query = "INSERT INTO SHEETSDB (ID, SHEETDATE, NUMBERANDDATE) VALUES (?,?,?)";
preparedStatement = null;
try {
preparedStatement = conn.prepareStatement(query);
preparedStatement.setInt(1, id);
preparedStatement.setDate(2, date);
preparedStatement.setString(26, numberAndDate);
} catch (SQLException e) {
System.out.println(e);
} finally {
preparedStatement.execute();
preparedStatement.close();
}
Alert confirmation = new Alert(AlertType.INFORMATION);
confirmation.setTitle("Finalizare generare fisa");
confirmation.setHeaderText(null);
confirmation.setContentText("Fisa " + txt_SheetNumber.getText() + "/" + sheetDate.getValue() + " a fost creata cu succes");
confirmation.showAndWait();
TableData();
}
}
}
}
#Override
public void initialize(URL url, ResourceBundle rb) {
//here I have some code that does not have any impact on my problem
}
My question is how can I efficiently check if the sheet number already exists in the database for that month without having to create the extra column. Let me know if you think that the actual solution is the best one, as the extra column is the only column that is unique, so that's the column I also use when I need to remove a row from the database.
Also I can't think of a solution to auto increment the sheet number and set it to the textfield, like check the last sheet number from current month and set it to the "txt_SheetNumber" textfield, if none set it to 1, so whenever I initialize the app to have already the sheet number in the textfield. If you can help me with that also would be much appreciated.
This is my first time working with Java or any other programming language, so feel free to comment on any aspect. The application is for me only to make my work easier.

After some digging, I found a solution for the 2nd problem. Let me know if I shall improve it.
int lastId() {
int newSheetNumber=0;
String query = "SELECT MAX(ID) FROM SHEETSDB WHERE MONTH(`SHEETDATE`)=MONTH(NOW()) AND YEAR(`SHEETDATE`)=YEAR(NOW())";
try {
preparedStatement = conn.prepareStatement(query);
rs = preparedStatement.executeQuery();
if (!rs.next()) {
newSheetNumber = 1;
}else {
newSheetNumber = rs.getInt(1) + 1;
}
preparedStatement.close();
rs.close();
//System.out.println("The new sheet is: " + newSheetNumber);
} catch (SQLException ex) {
System.err.println("Error " + ex);
}
return newSheetNumber;
}

Related

MySQL searching for data using Java [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I have this code for searching in the MySQL data table by id, but when I run the program it is giving me this error (Output : "Column 'Mart' Not Found"). I'm using JTextFiled to ask the user to enter the id that want to search for.
public void actionPerformed(ActionEvent event) {
if(event.getSource()== btn) {
try {
Connection connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);
PreparedStatement st = connection.prepareStatement("Select ID,user_name_1,password FROM Admin Where ID = ?");
int id = Integer.parseInt(text.getText());
st.setInt(1, id);
ResultSet rs = st.executeQuery();
if(rs.next()==false) {
JOptionPane.showMessageDialog(null, "The ID Not Found!!");
}
else {
String user = rs.getString("user_name_1");
text2.setText(rs.getString(user));
String pass = rs.getString("password");
text3.setText(rs.getString(pass));
}
}
catch (Exception e) {
System.out.print(e.getMessage());
}
}
}
Check if your column names are the same as the ones in the Database
Check if your connection string is connecting to the correct database
Ensure Database Driver is added
Try this:
public class DatabaseClass {
private String url = "YOUR URL";
private String username = "YOUR USERNAME";
private String password = "YOUR PASSWORD";
private static DatabaseClass theDB = new DatabaseClass();
private Connection c;
private DatabaseClass() {
try {
Class.forName("com.mysql.jdbc.Driver");
c = DriverManager.getConnection(url, username, password);
} catch (Exception ex) {
System.out.println("Error Connection: " + ex);
}
}
public Connection getC() {
return this.c;
}
public static DatabaseClass getInstance() {
return theDB;
}
}
And then, the click event:
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
try {
HashMap<Integer, String> data = new HashMap<>();
int id = Integer.parseInt(jTextField1.getText());
Connection c = DatabaseClass.getInstance().getC();
PreparedStatement s = c.prepareStatement("select * from yourTable where ID = ?");
s.setInt(1, id);
ResultSet theResult = s.executeQuery();
while (theResult.next()) {
int yourID = theResult.getInt("ID");
String yourData = theResult.getString("Email_Address");
data.put(yourID, yourData);
}
for (HashMap.Entry theEntry : data.entrySet()) {
jTextArea1.append(String.valueOf(theEntry.getKey()) + " " + theEntry.getValue() + "\n");
}
} catch (Exception ex) {
System.out.println("Error: " + ex);
}
}
Ideally this should work, but replace the query with your query and the connection string with yours.

Java - a GUI update button

i am trying to making an update button in my GUI form that can be edit a record in my DB but i missing something that i hope someone to help me
this the code of update method:
public int updateUser(Login user) //int
{
DatabaseConnection dbconn = new DatabaseConnection();
Connection conn = dbconn.getConn();
int rows = 0;
try
{
String sql = "UPDATE LOGIN set USER_NAME = ? , PASSWORD = ? , PRIVILEGE_ID = ?";
PreparedStatement pStm = conn.prepareStatement(sql);
//fill SQL parameters from user: //
pStm.setString(1, user.getUserName());
pStm.setString(2, user.getPassword());
pStm.setInt(3, user.getPrivilegeId());
rows =
pStm.executeUpdate();
}
catch (SQLException ex) {
System.out.println("SQLException: " + ex.getMessage());
}
finally
{
try {
conn.close();
} catch (SQLException ex) {
System.out.println("SQLException: " + ex.getMessage());;
}
}
return rows;
}
code in java swing for update button:
private void updateUserLayerActionPerformed(java.awt.event.ActionEvent evt) {
// 1-get data from user and check it: //
String _name = nameLayer.getText().trim();
String _paswrd = passLayer.getText().trim();
String _prvName = privLayer.getSelectedItem().toString();
//get Privilege_Id from DB:
PrivilegeHandeler prvHndler = new PrivilegeHandeler();
int prvId = prvHndler.getPrivilegeByName(_prvName);
if(_name.length() >0 && _paswrd.length() >0 && prvId> 0)
{
Login user = new Login();
user.setUserName(_name);
user.setPassword(_paswrd);
user.setPrivilegeId(prvId);
//update User: //
loginHandeler loghndlr = new loginHandeler();
int rows =
loghndlr.updateUser(user);
if (rows >0)
{
usrFormErorr.setText("user has been added successfully :)");
nameLayer.setText("");
passLayer.setText("");
privLayer.setSelectedIndex(0);
}
else
{
usrFormErorr.setText("updated failed, try again");
}
}
else
{
usrFormErorr.setText("please, fill the required fields first");
}
}
My problem is this:
1-i am trying to enter an info to edit then update but always get an error updated failed, try again that i made it to get a message when there is a problem
Kindly help. A working code would be very highly appreciated. Thanks in advance.

Get selected JComboBox value and add to SQL query for second JComboBox

I am designing a simple database application that features 2 jComboBoxes in the GUI. The first jComboBox is populated with the results of an SQL query. I would like the second jComboBox to populate with the results of a second query that incorporates the user selected value in the first box, but I can't quite get it to work.
I have created 2 classes, one that draws the GUI and contains the main method, and a second class that queries my Oracle database.
My GUI class:
public class TestUI extends javax.swing.JFrame {
// Create new form TestUI
public TestUI() {
initComponents();
}
#SuppressWarnings("unchecked")
private void initComponents() {
jPanel1 = new javax.swing.JPanel();
jComboBox1 = new javax.swing.JComboBox<>();
jTextField1 = new javax.swing.JTextField();
jComboBox2 = new javax.swing.JComboBox<>();
jButton1 = new javax.swing.JButton();
jButton2 = new javax.swing.JButton();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
// Combo box 1 population
jComboBox1.removeAllItems();
createConnection c1 = new createConnection();
c1.getEmployee().forEach((employee) -> {
jComboBox1.addItem(employee);
});
jComboBox1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jComboBox1ActionPerformed(evt);
}
});
// ComboBox 2 population
jComboBox2.removeAllItems();
}
private void jComboBox1ActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add handling code here:
}
public static void main(String args[]) {
DRAW GUI
}
}
And my database class:
import java.util.List;
import java.util.ArrayList;
import java.sql.*;
public class createConnection {
String empName;
public Connection createConnection() {
try {
Class.forName(driver);
java.sql.Connection conn = DriverManager.getConnection(DB_URL, DB_username, DB_password);
return conn;
} catch (ClassNotFoundException | SQLException e) {
return null;
}
}
// ComboBox 1
public List<String> getEmployee() {
List<String> list = new ArrayList();
Connection conn = createConnection();
try {
Statement stmt = conn.createStatement();
String query = "SELECT * FROM hr.employees ORDER BY last_name";
ResultSet results = stmt.executeQuery(query);
while (results.next()) {
list.add(results.getString("last_name"));
}
} catch (Exception e) {
System.out.println("Exception = " + e);
}
return list;
}
// Combo Box 2
public List<String> getEmpLocation() {
List<String> list = new ArrayList();
Connection conn = createConnection();
try {
Statement stmt = conn.createStatement();
String query = "SELECT country_id FROM hr.location WHERE hr.location.emp_name = " + empName;
ResultSet results = stmt.executeQuery(query);
while (results.next()) {
list.add(results.getString("last_name"));
}
} catch (Exception e) {
System.out.println("Exception = " + e);
}
return list;
}
}
I have left out irrelevant code like db connection variables and GUI coordinates etc.
I am wondering how to properly get the getEmpLocation() method in the database class to populate the 2nd ComboBox. This will involve adding code to both classes and passing the variable value but I can't figure it out! Any help would be greatly appreciated here.
I'm assuming that you'd like select a value from your first JComboBox then click on a button to process your selected data and load new data to your second JComboBox.
In this case you need an ActionListener to your JButton instead of your JComboBox:
jButton1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
selectedName = (String) jComboBox1.getSelectedItem();
}
});
You also need to store your selected value in a variable. The getSelectedItem() method returns an Object so it needs to be cast to a String in your case.
Since we added an ActionListener to a button you dont need this one:
jComboBox1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jComboBox1ActionPerformed(evt);
}
});
In your createConnection class (by naming convention class names should start with a capital letter):
If you are not using try-with-resources statement you should close your connections after the catch block.
} finally {
if (conn != null) {
try {
conn.close();
} catch (SQLException ex) {
ex.printStackTrace();
}
}
}
You need to pass your selectedName variable to getEmpLocation() method:
public List<String> getEmpLocation(String name) {
You should use a PreparedStatement instead of Statement:
String query = "SELECT first_name FROM employees WHERE last_name = ?";
PreparedStatement ps = conn.prepareStatement(query);
ps.setString(1, name);
ResultSet results = ps.executeQuery();
To be honest I don't know what you'd like to achieve with your select queries. First, this select query won't work. Table name is LOCATIONS instead of location, and it doesnt have a column called emp_name.
"SELECT country_id FROM hr.location WHERE hr.location.emp_name = ?"
If you'd like to get locations you should use a query like this:
"SELECT dep.department_name, loc.city, cou.country_name
FROM employees emp, departments dep, locations loc, countries cou
WHERE emp.last_name = ?
AND emp.department_id = dep.department_id
AND dep.location_id = loc.location_id
AND loc.country_id = cou.country_id"
You can choose which location you'd like to use department, city or country name. But my main problem is that if you select last names first and put them in a JComboBox it is most likely you will get only one row of data, so there is no point in using the second JComboBox. Let's approach this problem from the other side. What if you select location first and then select your employee. That could solve this issue.
Quick Example:
You select all first names from database, then you can select proper last name.
Selecting all first name from database:
public List<String> getEmpFirstName() {
List<String> list = new ArrayList();
Connection conn = createConnection();
try {
Statement stmt = conn.createStatement();
String query = "SELECT DISTINCT first_name "
+ "FROM hr.employees "
+ "ORDER BY first_name";
ResultSet results = stmt.executeQuery(query);
while (results.next()) {
list.add(results.getString("first_name"));
}
} catch (Exception e) {
System.out.println("Exception = " + e);
} finally {
if (conn != null) {
try {
conn.close();
} catch (SQLException ex) {
ex.printStackTrace();
}
}
}
return list;
}
Selecting last name(s) based on first name using PreparedStatement:
public List<String> getEmpLastName(String name) {
List<String> list = new ArrayList();
Connection conn = createConnection();
try {
String query = "SELECT last_name "
+ "FROM employees "
+ "WHERE first_name = ?";
PreparedStatement ps = conn.prepareStatement(query);
ps.setString(1, name);
ResultSet results = ps.executeQuery();
while (results.next()) {
list.add(results.getString("last_name"));
}
} catch (Exception e) {
System.out.println("Exception = " + e);
} finally {
if (conn != null) {
try {
conn.close();
} catch (SQLException ex) {
ex.printStackTrace();
}
}
}
return list;
}
Update your ActionListener:
jButton1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// Store selected value
selectedName = (String) jComboBox1.getSelectedItem();
// Create Connection and pass selected value to getEmpLastName
createConnection c1 = new createConnection();
names = c1.getEmpLastName(selectedName);
// Clear your second comboBox and fill with data
jComboBox2.removeAllItems();
for (String lastName : names) {
jComboBox2.addItem(lastName);
}
}
});
Try to select common names like Alexander, David, James, John, Julia and so on.

Fetching row from Cassandra table with Spring

Hello am trying to fetch 10 rows of data from Cassandra table. But on each request same 10 row is returning. Please see my logic here. and advise me where am doing wrong here-
public class CustomerRequestDaoImpl implements CustomerRequestDao
{
private static Cluster cluster;
#Resource
private CassandraSessionFactory cassandraSessionFactory;
/** The ProductsByTagDaoImpl session. */
private Session session;
#Override
public List<CustomerRequest> getCustomerRequestData(final String productId, final String receiptPeriod)
{
final int RESULTS_PER_PAGE = 10;
session = cassandraSessionFactory.getSession();
final List<CustomerRequest> customerRequestdata = new ArrayList<CustomerRequest>();
try
{
final PreparedStatement statement =
session.prepare("select * from customer_request where product_id = :id and receipt_period = :receiptPeriod");
final BoundStatement boundStatement = new BoundStatement(statement);
boundStatement.setFetchSize(RESULTS_PER_PAGE);
boundStatement.setString("id", productId);
boundStatement.setString("receiptPeriod", receiptPeriod);
final ResultSet resultSet = session.execute(boundStatement);
final Iterator<Row> iter = resultSet.iterator();
final PagingState nextPage = resultSet.getExecutionInfo().getPagingState();
int remaining = resultSet.getAvailableWithoutFetching();
for (final Row rowdt : resultSet)
{
customerRequestdata.add(constructCustomerReq(rowdt));
if (--remaining == 0)
{
break;
}
}
}
catch (final Exception e)
{
e.printStackTrace();
}
return customerRequestdata;
}
#PostConstruct
public void init()
{
session = cassandraSessionFactory.getSession();
cluster = session.getCluster();
}
}
My Table-
My Table structure:-
CREATE TABLE customer_request (
product_id varchar PRIMARY KEY,
id varchar,
receipt_period varchar,
delivery_method_status varchar,
first_name varchar
);
return Response-
<e>
<deliveryMethodStatus null="true"/>
<firstName null="true"/>
<id>0b0352f6b3904</id>
<lastName Adkin="true"/>
<orderId>FORMS8a04e</orderId>
<orderItemId>FORMS8a04e-1</orderItemId>
<productId>PI_NAME_CHANGE</productId>
<receiptPeriod>2016-02-06</receiptPeriod>
<receivedDate null="true"/>
<requestData null="true"/>
Several remarks:
You should not re-prepare the query each time, it's an
anti-pattern. Prepare the statement only once and re-use it for each method call
The source code you show will always return the first page of
data because you break out of the for loop once remaining
variable counts down to 0. The PagingState object is not used
anywhere ...
You question is not clear either Hello am trying to fetch 10 rows of
data from Cassandra table. But on each request same 10 row is
returning. Which 10 rows do you want ? The first 10 rows ? The
10 rows after a threshold ?
Sample code for paging:
Note: prepared the following query only once: select * from customer_request where product_id = :id and receipt_period = :receiptPeriod LIMIT :lim and pass it along with the method
#Override
public List<Tuple2<String,CustomerRequest>> getCustomerRequestData(final String productId, PreparedStatement ps, final String receiptPeriod, String pagingState)
{
final int PAGE_SIZE = 10;
session = cassandraSessionFactory.getSession();
final List<CustomerRequest> customerRequestdata = new ArrayList<CustomerRequest>();
try
{
final BoundStatement boundStatement = ps.bind(productId, receiptPeriod, PAGE_SIZE);
boundStatement.setPagingState(PagingState.fromString(pagingState));
final ResultSet resultSet = session.execute(boundStatement);
final Iterator<Row> iter = resultSet.iterator();
final PagingState nextPage = resultSet.getExecutionInfo().getPagingState();
int remaining = resultSet.getAvailableWithoutFetching();
for (final Row rowdt : resultSet)
{
customerRequestdata.add(constructCustomerReq(rowdt));
if (--remaining == 0)
{
break;
}
}
}
catch (final Exception e)
{
e.printStackTrace();
}
return new Tuple2<>(nextPage.toString(), customerRe);
Please note the use of Tuple2 class to return the list of results as well as the paging state, serialized as a String to be passed easily to the front-end

Allowing column name to be specified makes it a potential SQL injection risk

I have these two methods where I was told that "the fact you allow the column name to be specified is (an SQL) injection risk". What does even mean? To be specified by whom? And how can I fix it?
public void tableChanged(TableModelEvent e) {
int row = e.getFirstRow();
int col = e.getColumn();
model = (MyTableModel) e.getSource();
String stulpPav = model.getColumnName(col);
Object data = model.getValueAt(row, col);
Object studId = model.getValueAt(row, 0);
System.out.println("tableChanded works");
try {
new ImportData(stulpPav, data, studId);
bottomLabel.setText(textForLabel());
} catch (ClassNotFoundException e1) {
e1.printStackTrace();
} catch (SQLException e1) {
e1.printStackTrace();
}
}
public class ImportData {
public ImportData(String a, Object b, Object c)
throws ClassNotFoundException, SQLException {
PreparedStatement prepStmt = null;
try {
connection = TableWithBottomLine.getConnection();
String stulpPav = a;
String duom = b.toString();
String studId = c.toString();
System.out.println(duom);
String updateString = "update finance.fin " + "set ? = ? " + "where ID = ? "+ ";";
prepStmt = connection.prepareStatement(updateString);
prepStmt.setString(1, stulpPav);
prepStmt.setString(2, duom);
prepStmt.setString(3, studId);
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (prepStmt != null)
prepStmt.close();
System.out.println("Data was imported to database");
}
}
}
What does even mean? :)
It means, that if the String was changed, you could put in SQL code to do something different, like updating a password, or garnting access to the systems.
To be specified by whom?
Any code which can access the column name, this is only a problem if the user has access to this field.
And how can I fix it?
Check that there really is no way for the user to specify this column name, and ignore the message

Categories