rollback not working in unit test junit 5 - java

I have rolled back the changes made in a database, but the changes are being made in the database. Since it;s a unit test I can't have the data being tested inserted in the database.
I tried to add a member in db and got that member through his id by result set, but the member is being added in the db. I gave rollback to stop the changes made in db, but it's not working, I can see the member being added to db. Any solution?
#Test public void TestAddMember() { Member member = new Member();
try ( Connection connect = BookControl_jdbc.connection()) {
try ( Statement stcheck = connect.createStatement()) {
connect.setAutoCommit(false);
//input parameters
String name = "lia";
int age = 20;
String gender = "F";
String status = "ACTIVE";
member.setAge(age);
member.setGender(gender);
# member.setName(name);
member.setStatus(status);
memberControl.addMember(member);
memberControl.viewMembers();
int memberId;
String singleMemberQuery = "SELECT Member_id,Member_name,Age,Gender, Member_Status FROM Member WHERE Member_name='" + member.getName() + "';";
ResultSet rs = MemberControlDao_jdbc.getStmtResultSet(singleMemberQuery);
assertTrue(rs.next());
memberId = rs.getInt("Member_id");
assertEquals(name, rs.getString("Member_name"));
assertEquals(age, rs.getInt("Age"));
assertEquals(gender, rs.getString("Gender"));
assertEquals(status, rs.getString("Member_Status"));
} finally {
connect.rollback();
}
} catch (Exception e) {
e.printStackTrace();
}
}

Related

SQLite database refuses to update and I'm not sure why

I'm using these two methods in order to update the balance of a bank app I'm writing, but the database refuses to update and I'm not sure why.
Function for getting how much to add:
public void addIncome(String cardNum,Scanner scanner){
System.out.println("Enter income: ");
int income = scanner.nextInt();
scanner.nextLine();
dataBase.addBalance(income,cardNum);
}
Prepared statement and function for query:
private final String ADD_BALANCE = ("UPDATE card SET balance=balance+? WHERE number=?");
public void addBalance(int amount, String number){
try (Connection con = this.dataSource.getConnection();
final var sql = con.prepareStatement(ADD_BALANCE)){
sql.setInt(1, amount);
sql.setString(2,number);
sql.executeUpdate();
}catch (SQLException throwables) {
throwables.printStackTrace();
}
}
You're missing a call to commit, meaning the transaction will implicitly rollback when the connection is closed (at the end of the try).
try (Connection con = this.dataSource.getConnection();
final var sql = con.prepareStatement(ADD_BALANCE)) {
sql.setInt(1, amount);
sql.setString(2, number);
sql.executeUpdate();
con.commit(); // HERE
}

Delete from DB in Java

I want to delete a row in DB and it works but here is the problem:
If I enter the value that exists in DB, it is deleted and I get a message "Your Booking is successful canceled"
But also if I enter the value that not exists in DB, I get the same message. Why if the condition does not work?
String sql = "delete from vaccines.patients where idNum = ?";
String res = "Your Booking is successfully canceled";
PreparedStatement state;
try {
state = con.prepareStatement(sql);
state.setString(1, member.getIdNum());
if (member.getIdNum().equals(null)) {
res = "Enter id";
}
state.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
res="Your Booking is not successfully canceled";
}
You must check the number of affected rows instead since an update statement not affecting any rows won't error out.
e.g.
int rowCount = state.executeUpdate();
if (rowCount == 0) {
throw ...;
}

JDBC: "SQLException:Column name is not found"

I have tried to use these two questions as a reference
JAVA - SQLException throws exist column not found
Strange SQLException: Column not found
However, none of it helped my case. I keep receiving
java.sql.SQLException: Column 'debut' not found.
this is my SQL
private List<MemberModel> getModelFromNickname(String test) throws SQLException {
List<MemberModel> result = new ArrayList<>();
String sql = "select distinct " +
"m.name," +
"m.visual," +
"m.branch, " +
"m.illustrator, " +
"m.debut3D AS debut " +
"FROM " +
"member_list as m, " +
"nickname AS n " +
"WHERE n.nick_id = m.nick AND n.nickname LIKE ?";
ResultSet ret= sqlAdapter.select(
sql, 1,test
);
while (ret.next()){
result.add(fillRecord(ret));
}
return result;
}
this is my MYSQLAdapter
public ResultSet select(String sql,int option, Object... params) throws SQLException {
PreparedStatement query;
try{
logger.info(params.length);
query = getConnection().prepareStatement(sql);
}
catch (Exception e){
throw new Error("Problem "+ e);
}
resolveParameters(query,option, params);
return query.executeQuery();
}
this is my fillRecord command
private static MemberModel fillRecord(ResultSet resultSet) throws SQLException {
MemberModel member = new MemberModel();
member.name =resultSet.getString("name");
member.branch = resultSet.getString("branch");
member.debut_3d = resultSet.getBoolean("debut");
member.visual = resultSet.getString("visual");
member.illustrator = resultSet.getString("illustrator");
return member;
}
while this is my memberModel
public class MemberModel {
public String name = "";
public int social_media = 0;
public int nick = 0;
public String branch = "";
public boolean debut_3d= true;
public String illustrator ="";
public String visual = "";
}
I tried to use
ResultSetMetaData rsmd = sqlAdapter.getConnection().prepareStatement(sql).getMetaData();
for(int i =1; i<= rsmd.getColumnCount();i++){
System.err.println(rsmd.getColumnCount()+"\n"+rsmd.getColumnName(i));
}
which gives me the following (I don't know how it somehow managed to print more than 5. But, all of it except "debut" can be found)
5
name
5
visual
5
branch
5
illustrator
5
debut
5
name
5
visual
5
branch
5
illustrator
5
debut
This indicates that the debut column should exist yet I still get that exception. Where did I do wrong? I make sure that it is case sensitive just in case. The data type for "debut" column is boolean in my localhost XAMPP MySQL. If I erase member.debut_3d = resultSet.getBoolean("debut"); within fillrecord... Everything works perfectly fine
Rather get values by labelName trying column number.
private static MemberModel fillRecord(ResultSet resultSet) throws SQLException {
MemberModel member = new MemberModel();
member.name = resultSet.getString(1);
member.branch = resultSet.getString(3);
member.debut_3d = resultSet.getBoolean(5);
member.visual = resultSet.getString(2);
member.illustrator = resultSet.getString(4);
return member;
}
resultSet.getBoolean("debut3D"); // Instead of "debut"
The column in the database table is called "debut3D".
BTW you are not closing PreparedStatement and ResultSet. I would use try-with-resources.
The column name is "debut3D" not "debut", thats why you are getting the error.
Update below line with correct column name,
member.debut_3d = resultSet.getBoolean("debut3D");

Retrieve fields from object list in Java

I wrote a small program to retrieve records in my email queue table to process and send email. While using JDBC to achieve this, as shown below:
MySqlConnect con=new MySqlConnect();
public PreparedStatement preparedStatement = null;
public Connection con1 = con.connect();
//pick up queue and send email
public void email() throws Exception {
try{
while(true) {
String sql = "SELECT id,user,subject,recipient,content FROM emailqueue WHERE status='Pending' ";
PreparedStatement statement = con1.prepareStatement(sql);
ResultSet rs = statement.executeQuery();
while (rs.next()) {
String subject = rs.getString("subject");
String recipient = rs.getString("recipient");
String content = rs.getString("content");
String id = rs.getString("id");
String username = rs.getString("user");
String emailStatus = "DONE";
String errormsg=sendEmail(recipient, subject, content, id,username);
if (!errormsg.equals("")) {
emailStatus = "FAILED";
}
TerminalLogger.printMsg("Status : " + emailStatus);
}
statement.close();
rs.close();
}
}
}catch(Exception e){
e.printStackTrace();
TerminalLogger.printMsg("Exception: "+e.toString());
}
con1.close();
Thread.sleep(2000);
}
The above works fine since it retrieve email records where the status is pending and pass the subject, content, recipient, etc to sendemail method and done.
I wanted to achieve the same goal but using JPA persistence instead. So I wrote this method:
public Object getrecords() {
try {
String sql = "select p.id,p.user,p.subject,p.recipient,p.content from Emailqueue p where " +
"status='Pending'";
List<Object[]> resList =(List<Object[]>) em.createQuery(sql).getResultList();
if (resList == null) {
throw new Exception("Error with selection query.");
}
if (resList.size() > 0) {
return resList;
}
// msg = "Setting <" + name + "> not found.";
return null;
} catch (Exception e) {
msg = CoreUtil.wrapMsg(CoreUtil.FUNC_ERROR,
this.getClass().getName(), "get(" + "Pending" + ")", e.getMessage());
return null;
}
}
It has no issue retrieving the records and size in the table. And I called this method in the email(). Something like:
Object records = ejbCon.getSettingsFacade().getrecords();
From here, I can't figure how do I loop the records, to get each of the value in each field. For example, if there's 2 pending email records, I should need to retrieve each of its content, subject, recipient, etc and pass to sendemail method.
Also, retrieving these records is already taxing to my program since it takes long time to close the application compared to using JDBC (it's faster and I guess more efficient?).
So, I also need to consider the performance by doing using this method.
Edit
I should have clarified this better to explain what I'm trying to achieve.
So I have that email queue table in this form:
id user subject content recipient status
1 user1 test example abc#example.com Pending
2 user2 test2 example cde#example.com Pending
So before this, I was using resultset in JDBC to obtain each individual field values for id:1 and pass them to the send method, and proceed with id:2 and do the same, an iteration. Now I want to achieve the same way by using the object I retrieve but I can't specify which fields value it's able to get. So I am stuck.
There are many ways to achieve your desired result but the easiest way you can do is to create a parameterized constructor in your Emailqueue class and change your query to
String sql = "select NEW
Emailqueue(p.id,p.user,p.subject,p.recipient,p.content) from Emailqueue p
where " +
"p.status='Pending'";
List<Emailqueue> resList =(List<Emailqueue>)
em.createQuery(sql).getResultList();
this way you can normally iterate over List using foreach loop.
If i understood what is your correctly needs, Try to loop your resList.
And i recommend to you don't get Object type.
List<Emailqueue> resList = em.createQuery(sql, Emailqueue.class).getResultList();
for (Emailqueue email : resList) {
String subject = email.getSubject();
// something do.
}
Here the simple way to get data based on query.
If you are using Entity Manager for query and use HQL, u can just simply return the class data. here is the sample :
TypedQuery q = man.createQuery("SELECT u FROM YourTable u WHERE u.col1 =:col1 and u.col2 =:col2", YourCalss.class)
.setParameter("col1", col1)
.setParameter("col2", col2);
result = q.getResultList();
If you want with custom result, then u can modify the current class of entity into another class.
List<CustomClass> result = null;
EntityManager man = PersistenceUtilities.getEntityManagerFactory().createEntityManager();
try {
TypedQuery q = man.createQuery("SELECT NEW " + CustomClass.class.getCanonicalName() + "(u.col1,u.col2) "
+ "FROM YourTable as u ", CustomClass.class);
if (q.getResultList().size() > 0) {
result = q.getResultList();
}
} catch (Throwable t) {
Main.logger.error(t.getMessage());
} finally {
man.close();
}
return result;

Trouble inserting data into a MySQL database

I am developing a desktop application in Netbeans. I am trying to insert a record into database. The very strange problem I am having is that when I press the save button no error occurs, everything works perfect. But when I check my DB, there is no data in there. But when I try to insert data directly in phpmyadmin through query then it inserts the record after the ID (auto increment) that has been generated before when I try to save data through desktop app. I know It is difficult to explain. Let me give you all a bit more explanation
For example my database is all clear and I am trying to save my first record
Through desktop app I pressed the save button
when I checked the database there is no record there
Here above If data was saved successfully then the record ID has to be 1
But now I am inserting the record by going into phpmyadmin and manually typing the quering in sql tab
now the id of the record should be 1 but the id is 2.
So it means through desktop app data is saving but somewhere hidden which I can't see and also It is remembering the id. I hope you undertstand my question.
If I pressed save button 3 times after then I insert some data in phpmyadmin the id of that record is 4.
I don't know what the problem is?
Here is my code :
public class DBConnectionManager {
private static String DRIVER_NAME = "com.mysql.jdbc.Driver";
private static String HOST_NAME = "localhost";
private static String PORT_NUMBER = "3306";
private static String DB_NAME = "sales";
private static String USER_NAME = "root";
private static String PASSWORD = "";
public static Connection openConnection() throws Exception {
Class.forName(DRIVER_NAME);
String jdbcURL = "jdbc:mysql://"+HOST_NAME+":"+PORT_NUMBER+"/"+DB_NAME;
Connection connection = DriverManager.getConnection(jdbcURL,USER_NAME,PASSWORD);
connection.setAutoCommit(false);
return connection;
}
}
public void addSupplierDetail() {
String contact_name = txt_contactName.getText();
String shop_name = txt_shopName.getText();
String city = txt_city.getText();
int phone = Integer.parseInt(txt_phone.getText());
int mobileNo = Integer.parseInt(txt_mobile.getText());
String address = txt_address.getText();
Supplier supplier = new Supplier();
supplier.setContactName(contact_name);
supplier.setShopName(shop_name);
supplier.setCity(city);
supplier.setPhone(phone);
supplier.setMobileNo(mobileNo);
supplier.setAddress(address);
connection = DBConnectionManager.openConnection();
SupplierDAO dao = new SupplierDAO(connection);
try {
if (dao.addSupplier(supplier)) {
connection.close();
JOptionPane.showMessageDialog(null, "data save");
// Dashboard dashboard = new Dashboard();
//dashboard.setVisible(true);
} else {
JOptionPane.showMessageDialog(null, "not saved");
}
} catch (Exception e) {
JOptionPane.showMessageDialog(null, e);
}
}
public boolean addSupplier(Supplier supplier) throws Exception {
String sql = "INSERT INTO suppliers"
+ "(sup_name,sup_address,city,mobile_no,phone,shop_name)"
+ "VALUES (?,?,?,?,?,?)";
PreparedStatement ps = connection.prepareStatement(sql);
ps.setString(1, supplier.getContactName());
ps.setString(2, supplier.getAddress());
ps.setString(3, supplier.getCity());
ps.setInt(4, supplier.getMobileNo());
ps.setInt(5, supplier.getPhone());
ps.setString(6, supplier.getShopName());
System.out.println(ps);
int rowscount = ps.executeUpdate();
System.out.println("no of rows updated: " + rowscount);
ps.close();
return rowscount > 0;
}
try the debugger, if everything is executed as expected, check the autoCommit property of your statement (or connection I forgot to which one it is bound)
Since the auto-increment seems to be happening, as you said. Looks like auto commit is set to false. You can try to set it at connection level, by calling connection.setAutoCommit(true) or you can do it only for that transaction by calling connection.commit().

Categories

Resources