update the picture in database - java

Hello! I am creating an app for students database. Recently I got a problem when I want to change data that is related to the specific student. Especially problems occur when I want to change the picture for the specific student. I need to check if the picture belongs to the student or not. I store my pictures to the folder if I change the picture, I delete previous one and create a new one. My question about how to check if a picture belongs to the specific student?
I check students in this way.
// get the name of the student from first table getValueTableName
// get the name of the picture from first table getValueTablePicture
getValueTableName = jTable1.getModel()
.getValueAt(jTable1.getSelectedRow(), 0).toString();
getValueTablePicture = jTable1.getModel()
.getValueAt(jTable1.getSelectedRow(), 3).toString();
File sourceFile = new File(getValueTablePicture);
setPicture = sourceFile.getName();
// GET NAME OF THE STUDENT AND THE PICTURE FROM DATABASE AND COMPARE
// THEM TO THE CURRENT USER
try {
CallableStatement statement = null;
Connection data = getmyConnection();
statement = data.prepareCall("{call editStudentByName}");
myResults = statement.executeQuery();
while (myResults.next()) {
// COPY PATH IN getEditName
getEditName = myResults.getString("Name");
// COPY PATH IN getEditPicture
getEditPicture = myResults.getString("Picture");
// add students from database to array
// mylist.add(getEditName.concat(getEditPicture));
mylist.add("\n");
}
myResults.close();
} catch (Exception c) {
c.printStackTrace();
}
// I don't know how to move from this point when I check names with loop
// I check the student with the loop
for (String person : mylist) {
if (getValueTableName.concat(sourceFile.getName()).equals(person) == true) {
}
System.out.print(getValueTableName.concat(sourceFile.getName())
.equals(person));
errors.append(
"- Please choose another picture or rename it!\n Picture ")
.append(getEditPicture)
.append(" is exist for a student " + getEditName)
.append("\n");
jTextField3.requestFocusInWindow();
jTextField3.setText("");
}

The very first thing I'd do is not using separate Strings with strange names like getEditName - this is confusing. Consider having POJO (Student.class) and working with that
So you want to replace single student picture? Why do you have to iterate some array in this case? You should get single student from database (by Id or via some unique set of attributes).
Ok, lets say you have a list of students and you iterate over it. But you still have to change picture for single person so that there is no need to check.
Simply do
String pictureFileName = person.getPicture();//assming getPicture() method returns current picture path
and then save new picture with the same name. In this case old picture will be overwritten so that no issue with checks.
UPD:
If you want to check for picture existence you can do the same:
String pictureFileName = person.getPicture();
File f = new File(pictureFileName );
if(f.exists() && !f.isDirectory()) {
// do something, say report warning
}
UPD:
If you don't require an ability for students to share same file as a picture it's better to implement this at DB level as well via this https://www.w3schools.com/sql/sql_unique.asp - so that you simply won't be able to write two different student records with the same picture path field. In this case checks won't matter anymore and you can simply overwrite the picture file because it belongs to single student only

Finally, I got my things done. It was a very painful moment, but I got what I wanted. The problem was hidden in a column "Picture" in the table "Student" of my database. First, I add UNIQUE constraint ensures to my column that all values in a column are different. Second, I created two stored procedures:
CREATE DEFINER=`root`#`localhost` PROCEDURE `checkStudentByPicture`(
in picture_name varchar(100)
)
BEGIN
SELECT COUNT(*) FROM students_center.Student st WHERE st.Picture = picture_name;
END
The first procedure checks if my column has unique names and doesn't allow to add the same name to the column.
And I created a second one:
CREATE DEFINER=`root`#`localhost` PROCEDURE `getStudentNameByPicture`(
in name varchar(45),
in pic_name varchar(100)
)
BEGIN
SELECT COUNT(*) FROM students_center.Student st WHERE st.Name = name and st.Picture=pic_name;
END
The second procedure checks if the column "Picture" is related to the column "Name". If the column "Picture" is not related, the user doesn't allow to change the name.
Here is the code about checking if my data related to context:
private boolean validateFieldEditStudent() {
StringBuilder errors = new StringBuilder();
// call stored procedure checkStudentByPicture
File sourceFile = new File(jTextField3.getText());
String checkStudentName=jTable2.getValueAt(jTable2.getSelectedRow(), 0).toString();
try {
CallableStatement statement = null;
Connection data = getmyConnection();
statement = data.prepareCall("{call checkStudentByPicture(?)}");
statement.setString(1, sourceFile.getName());
myResults = statement.executeQuery();
while (myResults.next()) {
//COPY PATH IN pictureName
getPictureCount = myResults.getInt(1);
}
myResults.close();
} catch (Exception c) {
c.printStackTrace();
}
}
// call stored procedure checkStudentByPicture
try {
CallableStatement statement = null;
Connection data = getmyConnection();
statement = data.prepareCall("{call getStudentNameByPicture(?, ?)}");
statement.setString(1, checkStudentName);
statement.setString(2, sourceFile.getName());
myResults = statement.executeQuery();
while (myResults.next()) {
//COPY PATH IN pictureName
getStudentNameCount = myResults.getInt(1);
}
myResults.close();
} catch (Exception c) {
c.printStackTrace();
}
//check if data is related to the specific user
if(getFileChooserCount > 0) {
if(getStudentNameCount != 1) {
if(getPictureCount == 1) {
errors.append("- Picture "+sourceFile.getName()+" existed in the database!\n");
jTextField3.setText("");
jTextField3.requestFocusInWindow();
}
}
}
if (errors.length() > 0) {
JOptionPane.showMessageDialog(EditStudent, errors, "Warning!", JOptionPane.ERROR_MESSAGE);
return false;
}
return true;
}

Related

How would I join and insert data to the VO from 2 different database

Before I only have 1 SQL query where all of the column fields located in only 1 database. But now I need to move the StudentAccess to a different database. I need to join both of the database record and insert it to my VO object.
Database 1:
Select STUD_ID_NR, STUD_NM, STUD_LOG_ID
from Student
Database 2:
SELECT STUD_LOG_ID, STUD_LOG_ID from StudentAccess
WHERE logFlag= true
The STUD_LOG_ID will be the identifier for both of the table to join them.
This is my current code before that store data from only 1 Database
Class 1:
try
{
conn = getDataSource().getConnection();
stmt = conn.createStatement()
rs = stmt.executeQuery(StudentQuery);
List<StudentVO> listOfStudents = new ArrayList<StudentVO>;
if(null != rs)
{
while(rsv.next())
{
StudentVO validStudent = StudentsMapper.mapToVo(rs.getString(STUD_ID_NR),
rs.getString(STUD_NM), rs.getString(STUD_LOG_ID));
if(validStudents != null)
{
listOfStudents.add(validstudent);
}
StudentStore.setAllStudents(listOfStudents);
}
If the data's are coming from two database. how would I Still insert the STUD_LOG_IN_ID of the student to the VO if their STUD_LOG_ID had a match?
Let's assume that we can call both of the database in this class.
try
{
conn = getDataSource().getConnection();
stmt = conn.createStatement()
rs = stmt.executeQuery(StudentQuery);
rs2 = stmt.executeQuery(StudentAccessQuery);
List<StudentVO> listOfStudents = new ArrayList<StudentVO>;
if(null != rs2)
{
while(rsv.next())
{
}
}
if(null != rs)
{
while(rsv.next())
{
}
StudentStore.setAllStudents(listOfStudents);
}
I'm quite confused on how will I do it. should I add both record in an arraylist first then use the contain?
My VO contains the STUD_ID_NR,STUD_NM,STUD_LOG_IN_ID
Sugesstion
I don't know which SQL you are using but will suggest you to make your desired result set using a single query itself. It will be much easier to handle the data .
Connection to a DB is always costly , try to minimize the no of connections .It is for good practise.
Alternative
In java your approach is correct , however as per my understanding from the post contains may not work as 2 result sets may have different values.
If that is not the case you can use contains.
Below is an example without using contains.Here I have assumed 2nd result set may have multiple values as per each LOGIN_ID.
List<StudentVO> listFromDb1 = new ArrayList<StudentVO>;
List<StudentVO> listFromDb2 = new ArrayList<StudentVO>;
if(rs2 != null){
while(rsv.next())
{
// listFromDb1
//add result set from db1
}
}
if(rs!=null){
while(rsv.next())
{
// listFromDb2
//add result set from db2
}
}
List<StudentVO> finalList = new ArrayList<StudentVO>();
// considering listFromDb1 is your main dataset
for(StudentVO student : listFromDb1){
//boolean true =listFromDb2.stream().filter(s-> s.equals(student.getSTUD_LOG_IN_ID())).findAny().isPresent();
for(StudentVO student2 : listFromDb2){
if(student.getSTUD_LOG_IN_ID().equals(student2.getSTUD_LOG_IN_ID())){
//set the student values in new object and then add it to final list
StudentVO tempStu= new StudentVO(student,student2.getSTUD_LOG_IN_ID()); //it is just an example.
finalList.add(tempStu);
//use break here if 2nd resultset doesnot hold multiple log in id for same student;
}
}
}
StudentStore.setAllStudents(finalList);

Elements disappearing from an ArrayList

I'm having some troubles with this code:
ArrayList<Shop> listShops = new ArrayList<Shop>();
Shop currShop = new Shop();
String query = "SELECT * FROM Shop WHERE... ";
try {
PreparedStatement statement = connection.prepareStatement(query);
ResultSet rs = statement.executeQuery();
while(rs.next()) {
currShop.setName(rs.getString(1));
currShop.setDescription(rs.getString(2));
System.out.println(listShops.add(currShop));
}
} catch (SQLException e) {
e.printStackTrace();
}
System.out.println("List size: "+listShop.getSize());
for(Shop s: listShop) {
System.out.println(s.getName());
}
Output:
true
true
true
[...]
List size: 78
[78 empty strings]
And I'm not understanding why it is giving me those empty lines. I'm 100% sure that currShop works fine because I printed currShop.getName() and currShop.getDescription() (in the rs.next() while) and they both work. It also gives me "true" booleans indicating a successful insert into the ArrayList, so why doesn't it print anything?
You should create a new Shop object every time inside the while loop:
while(rs.next()) {
Shop currShop = new Shop();
currShop.setName(rs.getString(1));
currShop.setDescription(rs.getString(2));
System.out.println(listShops.add(currShop));
}
Otherwise, you are just adding a single Shop instance many times to the list, overwriting the name and description on each iteration.
Wim is right you must create a new Object inside the loop. Otherwise there is no point in overwriting the same old object again and again.
By using inside your while loop
Shop currShop = new Shop();
will be created a new instance everytime and the listShops.add(currShop) will have add new item on each insert.
This kind of mistake happens in the beginning, no worries keep learning !

Java JDBC - Navigate Through Records Within Database

I am having some trouble in returning the NEXT record within the database, my code currently only returns the last record entered. I have tried creating an instance of a List/ArrayList, tried adding statements to my createStatement(); and just tried everything. I've searched the web, however, I always seem to get the last value returned. I was hoping as to whether someone could help me out. I am using .Swing and this is all executed within an ActionListener.
Essentially I want this function to get the next record in the database. As opposed to returning the last record.
nextEmployee.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Connection connection = null;
Statement statement = null;
try {
Class.forName("org.sqlite.JDBC");
connection = DriverManager.getConnection("jdbc:sqlite:employeeDatabase.sqlite");
connection.setAutoCommit(false);
System.out.println("Read operation - database successfully opened");
statement = connection.createStatement(ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_READ_ONLY);
ResultSet resultset = statement.executeQuery( "SELECT * from employees" );
while (resultset.next()) {
ArrayList<Employee> selectAllEmployees = new ArrayList<Employee>();
String id = resultset.getString("id");
String name = resultset.getString("name");
String email = resultset.getString("email");
String gender = resultset.getString("gender");
String dob = resultset.getString("dob");
String Address = resultset.getString("address");
String Postcode = resultset.getString("Postcode");
String NIN = resultset.getString("NIN");
String JobTitle = resultset.getString("JobTitle");
String StartDate = resultset.getString("StartDate");
String Salary = resultset.getString("Salary");
idTextField.setText(id);
nameTextField.setText(name);
genderTextField.setText(gender);
dobTextField.setText(dob);
addressTextField.setText(Address);
postcodeTextField.setText(Postcode);
ninTextField.setText(NIN);
jobtitleTextField.setText(JobTitle);
startdateTextField.setText(StartDate);
salaryTextField.setText(Salary);
emailTextField.setText(email);
}
resultset.close();
statement.close();
connection.close();
} catch ( Exception e1 ) {
System.err.println( e1.getClass().getName() + ": " + e1.getMessage() );
System.exit(0);
}
}});
Thank you for your time and effort.
One of two things is happening. Either:
You have a bug in the code which populates the database, so you think you have rows A, B, and C in the database, but in fact you only have row C
Or:
Your code as listed populates your controls with the contents of row A, then it repeats to populate the exact same controls with contents of row B, and then the exact same controls once more with the contents of row C. So, naturally, the values you are left with are the values of the last row.
It helps to think precisely what it is that you are trying to do, precisely what is happening, precisely what you expected to happen instead, and most importantly, what makes you believe that the code should do that which you expect it to do rather than what it actually does.

How to Retrieve auto incremented ID value to a JLabel

I have a mysql Database which as Book Id (auto incrementing when I add data) and other rows. I have wrote a code to get the incremented value to a jLabel and it works fine too but still there is a one more little problem. assume I have entered 5 book details. so when I press the Save button (to save the details to database) it saves successfully and jLabel shows the incremented value as 6 (so it works fine).
Now the problem is, every time I closed my application and restart it, the jLabel shows the value as 1. Then when I save another book detail it skip to number 7 (which is the correct auto incremented ID). But Why is it showing the ID as 1, when I restart the application? It should read 7 even after I restart it. Here is the code sample. I have even call it in the class Constructor. But it doesn't seem to update. :(
private void autoGenerateId() {
if (true) {
try {
ResultSet result = new JDBC().getData("SELECT * FROM newbookstock");
if (!result.next()) {
jLabel5.setText("1");
} else {
ResultSet result2 = new JDBC().getData("SELECT LAST_INSERT_ID() AS bookid FROM newbookstock");
if (result2.next()) {
int id = result2.getInt("bookid") + 1;
String ss = String.valueOf(id);
jLabel5.setText(ss);
} else {
System.out.println("OOOOO");
}
}
} catch (Exception e) {
e.printStackTrace();
}
} else {
System.out.println("Set focus to Jtext1");
}
}
let's digest your code.
ResultSet result = new JDBC().getData("SELECT * FROM newbookstock");
if (!result.next()) {
This if condition will evaluate to false if the table is empty. So this is not where you are setting the label as 1
} else {
ResultSet result2 = new JDBC().getData("SELECT LAST_INSERT_ID() AS bookid FROM newbookstock");
Ah, but what do you get here when you first start the program? 0. Why because you have not inserted any values into the table with your current connection.
What you ought to do is
SELECT COUNT(*) FROM newbookstock
where you do
SELECT * FROM newbookstoc
or perhaps you might want MAX(id) instead of count(*) but select * is definitelly not what you should be using.
and use that value as your initial value. In other news, you have
new JDBC().getData(...)
in two locations. You shouldn't open multiple connections like this. Open the connection once and reuse it.
update: your snippet to set the initial value might look like:
JDBC conn = new JDBC();
ResultSet result = jdbc.getData("SELECT COUNT(*) as C FROM newbookstock");
jLabel5.setText(result2.getString("C"));

Fitting a whole row of a MySQL table onto a single JLabel in Java

I have Java code the successfully connects Java to MySQL.
I have two classes. One that creates the GUI with Java and another class that specifically gets information from MySQL.
I'm trying to find a good way to put a whole row of information as a String into each JLabel on MyGUI.
Here is my code in each class (excluding connecting to the database):
CLASS 1
String result = "";
contactsList()
{
//extra classes
db=new database();
result = db.getContact();
label1 =new JLabel(result);
CLASS 2
PreparedStatement pst, pst2;
ResultSet rs, rs2;
pst2 = con.prepareStatement("select LastName, FirstName from contacts");
public String getContact()
{
String result2 = "";
try {
rs2=pst2.executeQuery();
while (rs2.next())
{
result2 = rs2.getString(1);
}
return result2;
}
catch (Exception e) {
// TODO Auto-generated catch block
System.out.println("error while validating"+e);
return "";
}
}
Right now the rows in my Contacts table in MySQL has columns separated by commas
1, Rivera, Angelo, 2890 something st. ventura 93003, Null
2, Person, Random, 1223 I dunno ave. Camairllo 93001, 423-123-5313
Right now when I try to put a whole row in the "label1" the only text it shows is "Person".
How do I make it so it shows the whole Row in the JLabel?
Also how would I format the code so I can call the the function to get the next row of information and put it into another label?
Thanks.
You are only asking it to retrieve one column from your result set by the looks of things :
result2 = rs2.getString(1);
If you want to display more data, you just need to retrieve it and format it somehow :
result2 = rs2.getString(1) + " : " + rs2.getString(2);
for example.
But there are other problems with the select statement I think.
select LastName, FirstName from contacts
will retrieve the LastName and FirstName from every row in the database. The way your loop construct works means that result2 will contain the data for the last row in the table only. Is that what you are trying to achieve?
I would suggest using a JTable for this. Read the section from the Swing tutorial on How to use JTable for more information.
Then you might want to check out Table From Database. The Table From Database Example code may be the easiest way to start.

Categories

Resources