Jar in external libraries but cannot import in code

(more info at bottom)

I am using Maven to fetch the MySQL Connector for java

dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.16</version>
</dependency>

As such, it shows up in my External Libraries (intellij)

screenshot of external libraries (intellij)

However, in my code, I cannot import java.sql.*, as java.sql is not an option.

screenshot of failed java.sql import

In addition, I have made sure that my Project Structure is correct, having the dependency set as Compile scope

screenshot of project structure

I have also invalidated cache.

I have been stuck on this issue for a bit and cannot find a resolution; any help is appreciated.

More info: java.sql
Works in java 8 projects
Works in blank java 12 projects (not created with openjfx 12 archetype)

Inside main I now have this line of code:

java.sql.Connection c = null;

The error message I get when running is:

Error:(37, 9) java: package java.sql is not visible
  (package java.sql is declared in module java.sql, but module com.github.phaserush does not read it)

Solution:

The error indicates you are using the Java module system, and the java.sql module (containing packages java.sql and javax.sql) is not part of the default set of modules loaded by Java. You will need to explicitly depend on it.

In your src/main/java edit your module-info.java and add requires java.sql;. For example:

module com.github.phaserush {
    requires java.sql;
}

Where com.github.phaserush is your module name based on the exception message in your question.

How to display all result from JLabel to JFrame (JDBC SQL query)

I have a problem with displaying all the labels contained in the loop. In the provided code, he receives only the last query result. It seems to me that the rest is covered. Any ideas ?

public static void ViewTable(Connection con) throws SQLException {
    java.sql.Statement stmt = null;
    JFrame submenu = new JFrame("View");
    submenu.setSize(500, 500);
    submenu.setVisible(true);
    JLabel text = new JLabel("Lista przystankow: ");
    submenu.add(text, BorderLayout.NORTH);
    String query = "SELECT * FROM Stacja";
    try {
        stmt = con.createStatement();
        ResultSet rs = stmt.executeQuery(query);
        while (rs.next()) {
            String idStacja = rs.getString("idStacja");
            String nazwa = rs.getString("nazwa");
            JLabel input = new JLabel(" " + idStacja + " " + nazwa);
            submenu.add(input, BorderLayout.CENTER);
            System.out.println(" " + idStacja + " " + nazwa);
        }
    } catch (SQLException e) {
        e.printStackTrace();
    }

}

Solution:

…receives only the last query result

Because you fill the JLabel in the while loop, with the same variable, instead you can use a global variable to combine all the results, then show the it in the end, you can use StringBuilder for example :

StringBuilder message = new StringBuilder();
while (rs.next()) {
    message.append(space)
        .append(rs.getString("idStacja"))
        .append(" ")
        .append(rs.getString("nazwa"))
        .append(" ");
}
JLabel input = new JLabel(message.toString());
submenu.add(input, BorderLayout.CENTER);

Denormalized table and duplicated data

My Java project uses pure JDBC for interacting with Oracle DB (v. 12). The transaction isolation level is Read Committed.

I have a highly denormalized table, which stores an entity in set of rows. I cannot change this. Unfortunately this table has to remain this way and the reasons are independent from me.

+------+------+---------+
| date | hash | ....... |
+------+------+---------+
| date | xyz  | ....... |
| date | xyz  | ....... |
| date | xyz  | ....... |

I have two columns identifying an entity – a date and a hash. Since each entity is stored as several rows, these columns are not really unique, or a primary key, but only indexed columns. Still I want to enforce a kind of “uniqueness”, meaning that only one entity exists at the time, no matter how many rows is it made of.

Such entity can be updated couple of times a day, resulting in different values, but also different number of rows.

To make all this happen, every time I update an entity, I do two or more queries within single transaction:

delete from "table" where "date" = ? and "hash" = ?
insert into "table" values (?, ?, .....)
insert into "table" ....
... -- as many inserts as needed to store whole entity

This works fine for a single instance of application. Unfortunately, I have 2 instances working simultaneously, trying to store exactly the same data at almost the same time (they are simply primary-backup instances, but backup is also persisting – this I also have no influence on).

If this was normalized table, the solution would be to use MERGE statement, but it won’t work here.

My current solution:

What I tried to do so far is to add one more column, an ID of the instance persisting, then executing INSERT statements using SELECT as a data source and putting condition to SELECTs that there must be no data for this date/hash and app ID, otherwise SELECT provides no data to insert.

I thought it would work, but apparently it does not. I still see duplicates. I think it’s because two transactions do their delete at first, still don’t see data yet to be committed by other transaction, thus perform inserts on their own. Then the “commit” is execute and boom. Both transactions insert their data.

Other approaches that I considered:

I guess also optimistic locking won’t work, because at the final version check both transactions can still consider version to not be changed, while they are actually changed by both transactions at the same time and are about to be committed this way.

I know I could switch transaction isolation to SERIALIZABLE, but it isn’t perfect either (first of all, Oracle driver will not serialize queries, but will do optimistic approach and fail with error in case of concurrent modification, I don’t like that, it’s a “programming by exception” paradigm, an anti-pattern, then the second disadvantage is performance of course).

Are there any other solutions to such a problem?

Solution:

Your requirements, as I read them are:

  • Database structure cannot change
  • Both application must update exactly the same data at the same time
  • Optimistic locking is out because it might cause errors or a performance degradation
  • Pessimistic locking is out for the same reasons as optimistic locking

It seems like the most important thing is not what data you’re changing but what data you are reading. You need a method of determining what data the users of your system (I can’t tell whether these applications are just maintaining data or also using it) should be served.

I assume what your current queries for serving data are something like:

select * from table where date = :1 and hash = :2

If you change this to the following then you’ll always select the most recent data and if there are duplicates in time you’ll pick the first application (essentially random – change to whatever ordering you want)

select *
  from ( select t.*
              , rank() over (partition by hash 
                                 order by date desc, app_id desc) as rnk
           from table t
                )
 where rnk = 1

You can maybe put this in a view?

Then, you’re able to essentially running two separate tables in a single table. You can use MERGE etc. and can change your DELETE/INSERT statements to:

merge into table o
using (select :1, :2 ... ) n
   on ( o.date = n.date
       and o.hash = n.hash
       and o.app_id = n.app_id
           )
 when matched then
      update
         set ...
 when not matched then
      insert (...

commit;

delete from table
 where date < :1 
   and hash = :2

commit;

where you’re using the same date and hash from your MERGE statement. If the DELETE fails you don’t really mind – you’re protected from selecting the wrong data because you’ve changed your SELECT queries.


Personally, I’d acknowledge that one of your requirements have to change.

If there’s any plans for adding additional applications I’d accept the performance degradation and perform updates on this table serially using a queuing mechanism.

If there’s no plans for adding additional applications take the simple approach now and start using a locking strategy (not pretty) and just handle some known errors.

Syntax Error at or near "00" at Position: 138

So I am trying to extract information from a PostgreSQL Database. Below is the method which extracts the data :

public ResultSet dashboardQuerySurveyWithSelectedActions(String startDate, 
        String endDate, String agents) throws SQLException {
    Connection connection = super.getNewConnection();
    Statement statement = connection.createStatement();
    String query = String.format("SELECT surveys_nps_rating, survey_agent_name, surveys_stream_item_key "
            + "FROM public.surveys "
            + "WHERE surveys_response_date BETWEEN %s AND %s"
            + "AND survey_agent_name IN %s", startDate, endDate, agents);
    ResultSet resultSet = statement.executeQuery(query);
    connection.close();
    return resultSet;
}

following is the error what i get when i call this method:

('Honorine') - Parameter for Agent
2017-12-19 18:30:00 UTC - Start Date
2017-12-21 18:29:59 UTC - End Date



org.postgresql.util.PSQLException: ERROR: syntax error at or near "00"
  Position: 138
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2455)
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2155)
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:288)
    at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:430)
    at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:356)
    at org.postgresql.jdbc.PgStatement.executeWithFlags(PgStatement.java:303)
    at org.postgresql.jdbc.PgStatement.executeCachedSql(PgStatement.java:289)
    at org.postgresql.jdbc.PgStatement.executeWithFlags(PgStatement.java:266)
    at org.postgresql.jdbc.PgStatement.executeQuery(PgStatement.java:233)
    at application.repository.SpredfastSurveysRepository.dashboardQuerySurveyWithSelectedActions(SpredfastSurveysRepository.java:48)
    at application.controller.ReportController.getDashboardOutput(ReportController.java:261)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:635)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:108)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:748)

I have ran this query in PGadmin and the query runs fine. I cannot find any syntax error in the query. Any help is highly appreciated.

Solution:

Don’t use statement like this, it can cause syntax errors or SQL Injection instead use PreparedStatement :

// (I assume that agents is a list)
//this will define placeholders for example (?, ?, ?) if you have 3 agents
String inClause = "(" + String.format("%0" + agents.size() + "d", 0)
    .replace("0", "?, ").replaceFirst(", $", ")");

String query = String.format("SELECT surveys_nps_rating, survey_agent_name, surveys_stream_item_key "
                + "FROM public.surveys "
                + "WHERE surveys_response_date BETWEEN ? AND ? "
                + "AND survey_agent_name IN %s", inClause);

The query should return something like this :

SELECT surveys_nps_rating, survey_agent_name, surveys_stream_item_key 
FROM public.surveys WHERE surveys_response_date BETWEEN ? AND ? 
AND survey_agent_name IN (?, ?, ?)

try (PreparedStatement pst = con.prepareStatement(query);) {
    pst.setDate(1, startDate);
    pst.setDate(2, endDate);
    //Then Iterate over the agents list and set the values to the placeholders
    for (int i = 0; i < agents.size(); i++) {
        pst.setString(i + 3, agents.get(i));//Why (i+3)? because you already set 2 params
    }

    //get your results
    ResultSet rs = pst.executeQuery();
}