简体   繁体   English

Java JPA和Java JDBC对于相同的MySQL查询返回不同的结果

[英]Java JPA and Java JDBC return different results for the same MySQL query

NOTE: I know there's a lot of code in here but you probably just need to look to the first 2 code blocks. 注意:我知道这里有很多代码,但是您可能只需要查看前两个代码块。

I've a query and from the results from that query I build an ArrayList of Station objects, ArrayList<Station> . 我有一个查询,并从该查询的结果我建立一个ArrayListStation对象ArrayList<Station>

I want to use JPA as it is more flexible to use on the long run, so I'm adapting my code to run on JPA. 我想使用JPA,因为从长远来看,它使用起来更加灵活,因此我正在调整我的代码以使其在JPA上运行。

So I give a list of Station objects to a method and this method will do some calculations and do station.setPingPong(); 因此,我为方法提供了Station对象的列表,该方法将进行一些计算并执行station.setPingPong(); if that station meets certain calculation criteria, not relevant to the question. 如果该电台符合某些计算标准,则与该问题无关。

The problem is the list from JPA originates 3871 PingPongs and the list from JDBC originates 3888 PingPongs, the correct one is 3888. Why this? 问题是来自JPA的列表源自3871 PingPong,来自JDBC的列表源自3888 PingPong,正确的是3888。为什么呢?

Here's my code where I build the objects with the data from the database: 这是我的代码,其中使用数据库中的数据构建对象:

for (int i = 0; i < uniqueStations.size(); i++) 
{

ArrayList<Station> stationDataList = new ArrayList<>();
ArrayList<Station> auxStationDataList = new ArrayList<>();
ArrayList<Station> pingPongProccessedData = new ArrayList<>();
ArrayList<Station> pingPongProccessedDataJPA = new ArrayList<>();

// Query using JDBC
String queryToApi = "SELECT * "
                    + "FROM " + readTable + " "
                    + "WHERE calling_station_id = '" + uniqueStations.get(i) + "' "
                    + "order by timestamp-acct_session_time, timestamp;";

// Query using JPA                    
String query = "SELECT timestamp-acct_session_time, timestamp, called_station_id "
                + "FROM " + readTable + " "
                + "WHERE calling_station_id = '" + uniqueStations.get(i) + "' "
                + "order by timestamp-acct_session_time, timestamp;";

// Using JDBC, here Station objects are created inside getStationData method, inserted into the list and returned.
stationDataList = Database.getInstance().getStationData(api.getConnectionSourceServer(), query, false);

// Using JPA, JavaLogs is my Class Entity from the database (it represents my table and was generated by NetBeans)
List<JavaLogs> javaLogsList =  api.executeSelectQuery(queryToApi, JavaLogs.class, "TesteV2PU");
int repetitionSTA = 0;
// Now I'm creating the Station objects                    
for(JavaLogs javaLogs : javaLogsList)
{
    int id = javaLogs.getIdacesso();      
    long timestamp = javaLogs.getTimestamp();
    long accountSessionTime = javaLogs.getAcctSessionTime();
    int startTime = (int) (timestamp - accountSessionTime);
    int endTime = javaLogs.getTimestamp();
    String accessPoint = javaLogs.getCalledStationId();
    int ttPrevious = 0;
    int ttNext = 0;
    int pPong = 0;
    Station station = new Station(id, startTime, endTime, accessPoint, stationAnonymized++, repetitionSTA++, ttPrevious, ttNext, pPong);

    auxStationDataList.add(station);
}

// The problem comes here, pingPongProccessedData does have the correct computation of Station objects
// But pingPongProccessedDataJPA doesn't have the correct computation of Station objects
// In other words, pingPongProccessedDataJPA is WRONG and pingPongProccessedData is correct.

pingPongProccessedData = detectPingPong(accessThreshold, transitionThreshold, stationDataList);
pingPongProccessedDataJPA = detectPingPong(accessThreshold, transitionThreshold, auxStationDataList);

pingPongStationList.addAll(pingPongProccessedData);
pingPongStationListJPA.addAll(pingPongProccessedDataJPA);

}

int totalPingPongsJDBC = 0;
int totalPingPongsJPA = 0;

for(Station station : pingPongStationList) 
{
    if(station.getPingPong() == 1)
    {
        totalPingPongsJDBC++;
    }
}

for(Station station : pingPongStationListJPA) 
{
    if(station.getPingPong() == 1)
    {
        totalPingPongsJPA++;
    }
}

// Here I get in the console: TOTAL PingPongs JPA: 3871 TOTAL PingPongs JDBC: 3888
System.out.println("TOTAL PingPongs JPA: " + totalPingPongsJPA + " TOTAL PingPongs JDBC: " + totalPingPongsJDBC);

And here is my getStationData method from my Databse Object: 这是我的Databse对象中的getStationData方法:

public ArrayList<Station> getStationData(Connection con, String query, boolean isStationAnonymizeRequired) throws SQLException
{
    ArrayList<Station> stationList = new ArrayList<>();

    Statement s = con.createStatement();
    ResultSet rs = s.executeQuery(query);

    int repetitionSTA=1;

    while (rs.next()) 
    {
        /*
         * SQL Retorns:
         * StartTime - EndTime - AP - STA
         * 
         * Objecto Station:
         * ID - StartTime - EndTime - AP - STA - RepetitionSTA - TransitionTimePrevious - TransitionTimeNext - PingPong
         */

        if(isStationAnonymizeRequired == false)
        {
            Station station = new Station(id, rs.getInt(1), rs.getInt(2), rs.getString(3), stationMacAddress, repetitionSTA, 0, 0, 0);
            stationList.add(station);
            repetitionSTA++;
            id++;
        }
        else
        { //                            (id, startTime, endTime, ap, sta, repetitionSTA, ttprevious, ttnext, ppong)
            Station station = new Station(rs.getInt(1), rs.getInt(2), rs.getInt(3), rs.getString(4),
                    rs.getInt(5), repetitionSTA, rs.getInt(6), rs.getInt(7), rs.getInt(8));
            stationList.add(station);
            repetitionSTA++;
        }
    }
    rs.close();
    s.close();
    stationMacAddress++;

    return stationList;
}

I know that the IDs are different, built differently but that has no problem because the IDs are not used in detectPingPong method. 我知道ID不同,构建方式不同,但这没有问题,因为在detectPingPong方法中未使用ID。

Just in case, here's my detectPingPong method: 以防万一,这是我的detectPingPong方法:

public ArrayList<Station> detectPingPong(int accessSessionTime, int transitionTime, ArrayList<Station> stationDataList)
{

    for(int i = 1; i<stationDataList.size()-1; i++) //i=1 to skip the first position and -1 to skip the last position
    {
        /*
         * StartTime - EndTime - AP - STA - TTprevious - TTnext - PPong - ID
         */

        /*
         * At current position values
         */
        int startTimeActual = stationDataList.get(i).getStartTime();
        int endTimeActual = stationDataList.get(i).getEndTime();
        String apActual = stationDataList.get(i).getAccessPoint();

        /*
         * get the values from the previous position
         * */ 
        int endTimePrevious = stationDataList.get(i-1).getEndTime();
        String apPrevious = stationDataList.get(i-1).getAccessPoint();

        /*
         * get the values from the next position
         * */
        int startTimeNext = stationDataList.get(i+1).getStartTime();
        String apNext = stationDataList.get(i+1).getAccessPoint();     


        //Calc transition times:
        int transitionTimePrevious = startTimeActual - endTimePrevious;
        int transitionTimeNext = startTimeNext - endTimeActual;

        stationDataList.get(i).setTransitionTimePrevious(transitionTimePrevious);
        stationDataList.get(i).setTransitionTimeNext(transitionTimeNext);


         /*
          * Testing the conditions to occur a pingpong
          * */
        if(transitionTimePrevious<0)
        {
            transitionTimePrevious=0;
            stationDataList.get(i).setTransitionTimePrevious(transitionTimePrevious);
        }


        if(transitionTimeNext<0)
        {
            transitionTimeNext=0;
            stationDataList.get(i).setTransitionTimeNext(transitionTimeNext);
        }


        /*
         * ***************************
         * *    TEST PING PONG       *
         * ***************************
         */


        if( endTimeActual - startTimeActual < accessSessionTime && 
                transitionTimePrevious < transitionTime &&
                transitionTimeNext < transitionTime &&
                apActual.equalsIgnoreCase(apPrevious) == false &&
                stationDataList.get(i).getRepetitionSTA() > 1 
           )
        {
            stationDataList.get(i).setPingPong();
        }

    }
    return stationDataList;
}

So, as the method ( detectPingPong ) is the same for both lists and I get different results I assume that the error is on the lists, therefore the objects in the list which leads to the construction of the objects. 因此,由于两个列表的方法( detectPingPong )相同,并且得到不同的结果,因此我认为错误在列表上,因此列表中的对象导致对象的构造。

You are mapping the results to a bean class( javalogs ). 您正在将结果映射到bean类( javalogs )。 Probably there is some retreived data that doesnot match with the JavaLogs fields. 可能有一些检索到的数据与JavaLogs字段不匹配。 Those retreived rows will be ignored. 那些退回的行将被忽略。 And that is why you see discrepancy between the results. 这就是为什么您看到结果之间存在差异的原因。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM