I have a Java application where I want to be able to kill queries made to several databases. I know how to get the queries in the information_schema.processlist, but the problem is I don't know how to kill those queries. Usually I would do it using KILL command, but I cant use it in java application (or at least I havent figured out how to do it).
I've been reading about the Statement.cancel but the problem is that the queries are created by another application. I've understood that you have to have Statement variable in the class where you want to cancel it.
if I can use Statement for this purpose, can someone please help me to understand how. I'm using MySQL database. I dont want to set timeout, because I want to be able to kill any query I want to.
These are some examples how I've tried to kill the process:
public synchronized void killProcesses(Set<Long> ids) {
for (long id : ids) {
String killCommand="Select 'KILL ' from processlist where id=:id";
Query query= queryManager.createQuery(killCommand);
query.setParameter("id", id);
query.getResultList();
}
}
public synchronized void killProcesses(Set<Long> ids) {
for (long id : ids) {
String killCommand="KILL " + id;
Query query= queryManager.createQuery(killCommand);
query.getResultList();
}
}
#HannoBinder solved the problem, the final solution is:
private String killQuery(long id) {
String killCommand="KILL " + id;
queryManager.getTransaction().begin();
Query query=queryManager.createNativeQuery(killCommand);
query.executeUpdate();
queryManager.getTransaction().commit();
return "OK";
}
And one that worked too, but isnt that simple:
public synchronized void killProcesses(Set<Long> ids) {
for (long id : ids) {
String killCommand="KILL QUERY " + id;
queryManager.getTransaction().begin();
Connection conn=queryManager.unwrap(Connection.class);
try {
Statement statement= conn.createStatement();
statement.execute(killCommand);
} catch (SQLException e) {
e.printStackTrace();
} finally {
queryManager.getTransaction().commit();
conn.close();
}
}
}
Related
I'm very new in openfire and first time using java, I got stuck when I trying to develop plugin for crud. Could you give me some sample to make crud plugin ability? Thanks for your help before...
You can start from this answer: Mapping Openfire Custom plugin with aSmack Client
and follow the official tutorial with first 3 points of the answer.
About CRUD:
Let's assume you want to audit all your messages as XML in your database, so you'll implement a PacketInterceptor just to keep an easy scenario.
Your class plugin will looks like:
public class MyCustomPlugin implements Plugin, PacketInterceptor {//foo}
in method initializePlugin you'll have an invokation like:
public void initializePlugin(PluginManager manager, File pluginDirectory)
{
InterceptorManager.getInstance().addInterceptor(this);
}
and in method interceptPacket something like that:
#Override
public void interceptPacket(Packet packet, Session session,
boolean incoming, boolean processed) throws PacketRejectedException {
if (!processed)
{
boolean done = doMyCRUDAction(packet);
}
if (!done)
{ //do something if error occourred}
}
now let's write on database:
private static final String AUDIT_CHAT =
"INSERT INTO MYTABLE(MESSAGEASXML) VALUES (?)";
private boolean doMyCRUDAction(Packet packet)
{
if ((packet instanceof Message))
{
Message message = (Message) packet.createCopy();
boolean isAudited = false;
Connection con = null;
PreparedStatement statement = null;
try {
con = DbConnectionManager.getConnection();
statement = con.prepareStatement(AUDIT_CHAT);
statement.setString(1, message.toString());
statement.executeQuery();
isAudited = true;
}
catch (SQLException e) {
Log.error(e.getMessage(), e);
}
catch (Exception ex)
{
Log.error(ex.getMessage(), ex);
}
finally {
DbConnectionManager.closeConnection(statement, con);
}
return isAudited;
}
}
please keep in mind this is a reduced snippet of a working code, so there can be some sintax to fix
If your CRUD must follow an explicit IQ request, you'll have to extends an IQHandler and create a custom IQ and send to the client in handleIQ(IQ packet) method. You can check in Openfire sourcecode about detailed and complex implementations.
(EDITED)
I am using the following code to check if my Postgres db is up and running. However if the machine running the db is slow (Not enough RAM for example) it sometimes pass but when i tried to get some real data from the db (a few millisec after) i fail. I guess because not all tables were loaded.
Here is my code:
public static boolean testDBConnection(boolean refreshFactory) throws Exception
Session session = null;
try {
if(refreshFactory){
ConnectionUtil.refreshSessionFactory();
}
session = ConnectionUtil.getSessionFactory().openSession();
String sql = "select 1";
session.createSQLQuery(sql).list();
return true;
}
catch (HibernateException e) {
String error = "Failed to connect db.";
throw ExceptionFactory.create(error);
}
finally{
if(session!=null){
session.close();
}
}
}
Is there a better way then "select 1"?
Thanks
I got a deadlock problem with mysql and an application that I am developing. The application, based on spring boot, integration and jpa, has different threads and all of them can access this service:
#Override
#Transactional()
public List<TwitterUser> storeTwitterUsers(List<TwitterUser> twitterUsers)
{
logger.debug("Store list of users, total: " + twitterUsers.size());
List<TwitterUser> savedUsers = new ArrayList<>();
for ( TwitterUser twitterUser : twitterUsers ) {
TwitterUser user = getTwitterUserById(twitterUser.getTwitterId());
if ( user != null ) {
twitterUser.setId(user.getId());
user = entityManager.merge(twitterUser);
} else {
//HERE THE EXCEPTION IS THROWN
entityManager.persist(twitterUser);
user = twitterUser;
}
entityManager.flush();
savedUsers.add(user);
}
return savedUsers;
}
#Override
#Transactional(readOnly = true)
public TwitterUser getTwitterUserById(Long id)
{
Query query = entityManager.createQuery("from TwitterUser u where u.twitterId=:id");
query.setParameter("id", id);
TwitterUser twitterUser = null;
//Throw Exception NoResultException
try {
twitterUser = (TwitterUser)query.getSingleResult();
} catch (NoResultException e) {
//no result found
}
return twitterUser;
}
When more than one thread is within the method storeTwitterUsers, mysql throw this error:
Deadlock found when trying to get lock; try restarting transaction
This is the full stack track of the error:
http://pastebin.com/nZEvykux
I already read those two questions:
How to avoid mysql 'Deadlock found when trying to get lock; try restarting transaction'
Getting "Deadlock found when trying to get lock; try restarting transaction"
but my problem seems slightly different because I got the exception when almost any thread tries to persist the object.
Is there a clean and easy way to resolve the problem without implementing a low level code check? Can Spring JPA automatically manage the deadlock situation?
Any help is really appreciated, I am struggling with that error!
I want to delete and insert triples from a sesame repository using SPARQL queries, and I want to execute both operations as a single transaction.
DELETE
INSERT
If an exception is thrown during the transaction, rollback is executed... but it seems not to work.
The problem is that, if an exception is thrown during the insert query, the rollback is executed, but the previously deleted triples are not recovered (Why?).
Here you have some code:
I have a class called OwlimConnector which wraps the repository connection and provides some methods to make SPARQL Queries.
In the constructor of this class, I set up the connection and I set the autocommit to false:
RemoteRepositoryManager repos_manager = RemoteRepositoryManager.getInstance(SERVER_URL, USER, PASSWORD);
repos_manager.initialize();
Repository ssr = repos_manager.getRepository(REPOSITORY);
rconn = ssr.getConnection();
rconn.setAutoCommit(false);
In OwlimConnector there is a method called executeUpdate:
public void executeUpdate(String queryString) throws RepositoryException, MalformedQueryException, UpdateExecutionException
{
Update up = rconn.prepareUpdate(QueryLanguage.SPARQL, queryPrefixString + queryString);
up.execute();
}
and these methods among others:
public void commit(){
rconn.commit();
}
public void rollback() {
rconn.rollback();
}
public void close(){
rconn.close();
}
On the other hand, I have a web service "updateUserGroup" wich uses the previous OwlimConnector and a data access object called UserGroupDAO:
#PUT
#Consumes(MediaType.APPLICATION_XML)
public Response updateUserGroup(UserGroup ug) {
try {
oc = new OwlimConnector();
} catch (OwlimInstantiationException e) {
return ResponseFactory.getError(e.getErrorMessage());
}
try {
UserGroupDAO ugdao = new UserGroupDAO(oc);
ugdao.delete(ug.getUri());
ugdao.add(ug);
oc.commit();
oc.close();
return ResponseFactory.getOK();
} catch (MandatoryFieldException e) {
oc.rollback();
oc.close();
return ResponseFactory.getError(e.getErrorMessage());
} catch (NotExistingResourceException e) {
oc.rollback();
oc.close();
return ResponseFactory.getError(e.getErrorMessage());
} catch (Exception e) {
oc.rollback();
oc.close();
return ResponseFactory.getError(new GenericException(e).getErrorMessage());
}
}
1 What ugdao.delete(ug.getUri()) does is to call the OwlimConnector method executeUpdate:
oc.executeUpdate("DELETE { " + usergroup + " ?p ?v . } WHERE { " + usergroup + " ?p ?v . }");
Here the triples are deleted even though there is no commit!
2 What ugdao.add(ug) does is:
To check that ug.getName() is not null or spaces, otherwise the MandatoryFieldException is thrown:
if (ug.getName() == null || ug.getName().equals("")){
throw new MandatoryFieldException("name");
}
Then, the data is inserted:
oc.executeUpdate("INSERT DATA { " + ug.getUri() + " a scmu:UserGroup ; scmu:hasName \"" + ug.getName() + "\" . }");
When ug.getName() is null or spaces the MandatoryFieldException exception is thrown and caught by updateUserGroup. Then the rollback is executed but the deleted triples are not recovered.
I donĀ“t know why this happens. Any Idea?
Thank you very much in advance
The solution is much easier than I thought. This is the answer I received from the Ontotext AD in the mailing list:
"you are using RemoteRepository so each update, is immediately sent to the remote repository at up.execute() and there it is autocommited immediately .
what you could do is instead of preparing and executing on each delete/add operation in your service to start collecting all individual updates (into a StringBuilder for instance) and on oc.commit() to prepare and execute the whole list of updates at once (and just clear the list on rollback, in case an exception is thrown)
Your update request can have multiple 'INSERT DATA' or 'DELETE DATA' updates ... "
And it works! Thank you.
So I have this username and password validation code using Java persistence.
public Subscriber validateLogin(String username, String password)
{
EntityManager em = getEntityManager();
Query q = em.createQuery("SELECT s FROM Subscriber s WHERE s.username = :username OR s.password = :password ");
q.setParameter("username", username);
q.setParameter("password", password);
try
{
return (Subscriber) q.getSingleResult();
}
catch (Exception e)
{
return null;
}
}
So I check if the subscriber return anything or null. Here is my code:
private void jButton3ActionPerformed(java.awt.event.ActionEvent evt)
{
// TODO add your handling code here:
SubscriberJpaController sjc = new SubscriberJpaController();
Subscriber sub = sjc.validateLogin(jTextField1.getText(), jPasswordField1.getText());
System.out.println(sub);
}
and it returns null. Anything wrong with my code or logic?
You should never query on the password.
The query you want to run is this:
m.createQuery("SELECT s FROM Subscriber s WHERE s.username = :username");
Once you have received the user, then you check the password validity in code. This is particularly important because you're obviously hashing your passwords. Right?
there might be an exception thrown when you do the query. you have to print the stacktrace to see the cause.
I guess (not sure) the problem could be at the line q.getSingleResult(); if other configurations were correctly set.
Jpa is expecting a unique result. however your query could generate a set of Subscribers by username=.. or password=.... e.g.
user a(uname,pwd)= ("usera","123")
user b(uname,pwd)= ("userb","123")
so the method getSingleResult() throws the exception.
also, you may consider to use jpa TypedQuery with generic instead of doing the class casting manually.