hibernate multiple update queries single transaction - mysql

I am using hibernate with mysql db but having trouble with multiple updates in single transaction
Here is my code
public void updateOEMUser(OEMUserDetailsDTO userDTO) throws Exception{
Session session = GCCPersistenceMangerFactory.getSessionFactory().openSession();
Transaction tx = null;
try{
String query = "update oemuserdata set full_name=\""+userDTO.getFullName()+ "\" ,contact_no=\""+userDTO.getContactNo() + "\" where user_id="+userDTO.getUserId();
String query1 = "update usermasterdata set account_status="+userDTO.getAccountStatus() + " ,user_name=\"" + userDTO.getUserName() + "\" where user_id="+userDTO.getUserId();
Query q = session.createSQLQuery(query);
Query q1 = session.createSQLQuery(query1);
tx = session.beginTransaction();
q.executeUpdate();
q1.executeUpdate();
tx.commit();
}catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
throw new RuntimeException("HibernateException_updateOEMUser");
}finally {
session.close();
}
}
The code works but when I make "q1.executeUpdate()" fail the record in "oemuserdata" is getting locked in Mysql.
Am I doing something wrong?

Try using such kind of pattern.
StringBuilder query = new StringBuilder();
query.append("UPDATE CLASSNAME_FIRST a ,");
query.append("CLASSNAME_SECOND b,");
query.append("SET a.full_name='"+userDTO.getFullName()",");
.....
int var = stmt.executeUpdate(query);

Ok I didin't find the solution but I found out what's happening here.
When I remove the connection after successful execution of q.executeUpdate() exception is thrown at the execution of q1.executeUpdate() and after catch block it goes in final block and tries to execute session.close(), but since there is no DB connectivity this also fails.
But Mysql still has the lock requested by q.executeUpdate(). That's why the row is locked until Mysql releases lock itself.

Related

SyntaxError Exception

#Override
public void start(Stage primaryStage) throws Exception{
try{
String fxmlName;
Connection con = DriverManager.getConnection("url","root","password");
Statement st = con.createStatement();
String qry = "select UpdateT from schema.update";
ResultSet rs = st.executeQuery(qry);
fxmlName = rs.getString("UpdateT");
// System.out.println(fxmlName);
st.close();
Parent root = FXMLLoader.load(getClass().getResource(fxmlName));
primaryStage.setScene(new Scene(root));
primaryStage.initStyle(StageStyle.UNDECORATED);
primaryStage.show();
}
catch (Exception e){
System.out.println(e);
}
}
Hey guys this is my code and its my first time on stack overflow and why I am getting this exception?
java.sql.SQLException: Before start of result set
UPDATE is a reserved word, so your DB objects should not use it. You can:
change the table name (i 'd prefer this)
use quotes every time to refer to that table

why is my database not updating? (using netbeans xampp mysql)

when i run the file, it accepts the query and says update success but when i check my database why does it not update?
private void btnUpdateDeleteActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
if(radioUpdate.isSelected()){
try{
Class.forName("com.mysql.jdbc.Driver");
cn=DriverManager.getConnection("jdbc:mysql://localhost:3306/soften?zeroDateTimeBehavior=convertToNull","root","");
st=cn.createStatement();
String sql="UPDATE `tblproductssales` SET "
+" product = ?,quantity = ?"
+" WHERE 'sale no' = ?";
PreparedStatement pst = cn.prepareStatement(sql);
pst.setString(1,editProduct.getText());
pst.setString(2,editQty.getText());
pst.setString(3,editSaleID.getText());
pst.executeUpdate();
JOptionPane.showMessageDialog(null,"success update");
//**when i run the file this JOPtionpPane shows
}catch(Exception e){e.printStackTrace();}
}
}
here is my database, the table name is tblproductssales

SqlDependency failed because A SELECT statement that cannot be notified or was provided

I'm trying to use SqlDependency, And I read articles Creating a Query for Notification, Query Notification Permissions from Microsoft. I double checked many times, it seems all meet what it needs which mentions in articles Here is my code.
private void InitialSqlDependency()
{
using (var connection = new SqlConnection(_connString))
{
connection.Open();
string message = string.Empty;
string query = #"SELECT ModifiedOn FROM [dbo].[ContainerTransactions]";
using (var command = new SqlCommand(query, connection))
{
command.Notification = null;
SqlDependency dependency = new SqlDependency(command);
dependency.OnChange += new OnChangeEventHandler(Dependency_OnChange);
if (connection.State == ConnectionState.Closed)
connection.Open();
SqlDataReader dr = command.ExecuteReader();
if (dr.HasRows)
{
dr.Read();
message = dr[0].ToString();
}
}
}
}
private void Dependency_OnChange(object sender, SqlNotificationEventArgs e)
{
_logger.Debug("ContainerWatch Dependency Fired!");
if (e.Type == SqlNotificationType.Change)
{
_logger.Debug("ContainerWatch Change Fired!");
this.InitialSqlDependency();
}
}
However, It always failed to subscribe. And I see SqlNotificationInfo returns Query which means A SELECT statement that cannot be notified or was provided. Here is my debug img
The SELECT statement is extremely simple, Is there any possible reason causing fail?
I found the root cause, because The statement must not reference tables with computed columns. I use a query below to see computed columns
SELECT * FROM sys.computed_columns WHERE object_id = OBJECT_ID('ContainerTransactions')
Therefore, I think I can't use SqlDependency on this table.

Does h2 have a query/clause similar to the WHERE IN in MySQL?

My code currently goes as follows:
public List<DeviceOrganizationMetadataHolder> getChildrenByParentId(List<String> parentIds) throws DeviceOrganizationDAOException {
List<DeviceOrganizationMetadataHolder> children = new ArrayList<>();
Connection conn;
PreparedStatement stmt = null;
ResultSet rs = null;
DeviceOrganizationMetadataHolder deviceMetadataHolder;
String[] data = parentIds.toArray(new String[parentIds.size()]);
try {
conn = this.getConnection();
String sql = "SELECT * FROM DEVICE_ORGANIZATION_MAP WHERE DEVICE_PARENT IN (?)";
stmt = conn.prepareStatement(sql);
data = parentIds.toArray(data);
stmt.setObject(1, data);
rs = stmt.executeQuery();
while (rs.next()) {
deviceMetadataHolder = this.loadOrganization(rs);
children.add(deviceMetadataHolder);
}
} catch (SQLException e) {
throw new DeviceOrganizationDAOException("Error occurred for device list with while retrieving children.", e);
} finally {
DeviceManagementDAOUtil.cleanupResources(stmt, rs);
return children;
}
}
However even though in the unit tests I try to pass an array with parentIds, the return remains null.
What I can gauge from this is one of the following:
The array data isn't getting properly read, therefore the output is coming as null.
WHERE IN is not supported by h2 or else there is a different implementation that needs to be used instead.
Where am I going wrong in this?
EDIT - There was a similar duplicate question that was tagged. While it suggested using a StringBuilder and a loop, I was looking for an answer stating how it could be done in a cleaner way using the query itself.
Try setting the parameter as a list instead of an array, ie replace
stmt.setObject(1, data);
with
stmt.setObject(1, Arrays.asList(data));
Figured it out.
There was an issue posted on the h2database GitHub about this exact problem. Followed the suggested edits and it worked!
Code after edits is as follows:
public List<DeviceOrganizationMetadataHolder> getChildrenByParentId(List<String> parentIds) throws DeviceOrganizationDAOException {
List<DeviceOrganizationMetadataHolder> children = new ArrayList<>();
Connection conn;
PreparedStatement stmt = null;
ResultSet rs = null;
DeviceOrganizationMetadataHolder deviceMetadataHolder;
Object[] data = parentIds.toArray();
try {
conn = this.getConnection();
String sql = "SELECT * FROM DEVICE_ORGANIZATION_MAP WHERE DEVICE_PARENT IN (SELECT * FROM TABLE(x VARCHAR = ?))";
stmt = conn.prepareStatement(sql);
stmt.setObject(1, data);
rs = stmt.executeQuery();
while (rs.next()) {
deviceMetadataHolder = this.loadOrganization(rs);
children.add(deviceMetadataHolder);
}
} catch (SQLException e) {
throw new DeviceOrganizationDAOException("Error occurred for device list with while retrieving children.", e);
} finally {
DeviceManagementDAOUtil.cleanupResources(stmt, rs);
return children;
}
}
As you can see, I've used an Object array for data instead and added an additional query inside the main query.
Followed the instructions given in the GitHub issue to a tee and it worked flawlessly.

SQL result convert into integer

I'm having trouble convert this String sql results into int. Can you guys tell how to accomplish this.
I'm doing this because I need this value set in to a JLabel that shows attendance count.
I've tried to search for the answer here, but I couldn't find it. Please can you guys help me with this problem?
public static int attendanceCount() throws ClassNotFoundException, SQLException {
String sql = "select count(accountNo) from attendance";
Connection conn = DBConnection.getDBConnection().getConnection();
Statement stm = conn.createStatement();
ResultSet rst = stm.executeQuery(sql);
return rst; // How do I convert this into integer?
}
This is what I need to accomplish.
private void setAttendanceTile() {
try {
int attendanceCount = AttendanceController.attendanceCount();
inHouseMembersLabel.setText(Integer.toString(attendanceCount));
} catch (ClassNotFoundException ex) {
Logger.getLogger(Home.class.getName()).log(Level.SEVERE, null, ex);
} catch (SQLException ex) {
Logger.getLogger(Home.class.getName()).log(Level.SEVERE, null, ex);
}
}
Or is there another way to accomplish this without doing this way?
Thanks.
get ResultSet.getInt(1):
int id = rst.getInt(1);
You could use ResultSet.getInt() method. It takes either a column index or a column name. Here's an example from Oracle.
In your case you would need the one which takes the index (note that index starts with 1, not 0).
As suggested earlier, try using .getInt() method.
Moreover, I would use PreparedStatement. It's important to use PreparedStatement, because it allows database to cache your queries.
Also, always close your Connection and ResultSet after using them.
public static int attendanceCount() throws ClassNotFoundException, SQLException {
final int COLUMN_NO = 1;
final String SQL = "select count(accountNo) from attendance";
Connection conn = DBConnection.getDBConnection().getConnection();
PreparedStatement stm = conn.prepareStatement(SQL);
ResultSet rst = stm.executeQuery();
int result = rst.getInt(COLUMN_NO);
try {
rst.close();
conn.close();
} catch (SQLException e) {} //ignore
return result;
}