简体   繁体   中英

DAO and Synchronization between threads

I'm developing a Javafx application, that synchronizes some data from two different databases. In the call method I get all the data and store it in an ArrayList . Then I loop through the ArrayList and I try to get that same data from the second database. If it exists I compare it for differences and if there are differences I update it. Otherwise, if it dosen't exist, I insert it via a DAO object method. The problem is that sometimes the second database takes some time to provide the response so the process continues its execution and the new data will be compared with old data. My question is, how can I stop the process until the data has all been fetched and then proceed to the synchronization logic?

@Override
protected Map call() throws Exception {
    Map<String, Integer> m = new HashMap();
    updateTitle( "getting the data ..." );
    int i, updated = 0, inserted = 0;
    // creating first database instance
    DAOFactory db1Dao = DAOFactory.getInstance( "db1" );
    //creating the first database dataObject instance
    Db1EmployerDAO empDb1Dao = db1Dao.getDAODb1Employer();
    // creating second database instance
    DAOFactory db2Dao = DAOFactory.getInstance( "db2" );
    //creating the second database dataObject instance
    Db2EmployeurDAO empDb2Dao = db2Dao.getDAODb2Employer();
    Employer emp;
    // getting all the object
    List< Employer > LEmpDb1 = empDb1Dao.getAll();
    updateTitle( "Data proccessing ..." );
    //for each data in the list
    for( i = 1; i <= LEmpDb1.size(); i++ ){
        if( isCancelled() )
            break;
        updateMessage( "Processing employer : "+ LEmpDb1.get( i-1 ).getNemploy() +" "+ LEmpDb1.get( i-1 ).getRaison() );

    //trying to get the object from the second database which the
    //process sometimes pass befor the result is getting which is my problem
        emp = empDb2Dao.getEmployerByNo( LEmpDb1.get( i-1 ).getNemploy() );
        if( emp != null){
            if( !LEmpDb1.get( i-1 ).equals( emp ) )
                if( empDb2Dao.update( LEmpDb1.get( i-1 ) ) ){
                    updated++;
                    LOG.log( "MAJ employeur : "+  LEmpDb1.get( i ).getNemploy()+" => "+LEmpDb1.get( i ).getDifferences( emp ) );
                }
        } else {
            if( empDb2Dao.insert( LEmpDb1.get( i-1 ) ) )
                inserted++;
        }
        updateProgress( i, LEmpDb1.size() );
    }
    m.put( "upd", updated );
    m.put( "ins", inserted );
    m.put( "all", LEmpDb1.size() );
    return m;
}

The getEmployerByNo method

public synchronized Employer getEmployerByNo( String no_emp ) throws DAOException {
    Employeur emp = null;
    Connection con = null;
    PreparedStatement stm = null;
    ResultSet res = null;
    try{
        con = dao.getConnection();
        stm = preparedRequestInitialisation( con, GET_BY_NO_SQL, no_emp );
        res = stm.executeQuery();
        if( res.next() ){
        //map is a function that map the database resultset data with the object properties
            emp = map( res );
            LOG.info( "getting the employer : "+ no_emp );
        }
    } catch( SQLException e ){
        throw new DAOException( e.getLocalizedMessage() );
    } finally{
        silentClose( res, stm, con );
    }
    return emp;
}

Look into using an ExecutorService and Future.get() as needed to wait for completion. See the documentation here and here . Here is a more-or-less complete example:

public class Application implements Runnable {

    private final ExecutorService pool = Executors.newCachedThreadPool();

    public void run() {
        Dao firstDao = new DaoImpl();
        Dao secondDao = new AnotherDaoImpl();

        FetchAllTask fetchAll = new FetchAllTask(firstDao);
        Future<?> fetchAllFuture = pool.submit(fetchAll);
        try {
            fetchAllFuture.get();
        } catch (Exception e) {
            // TODO handle
            System.out.println("An exception occurred!");
            e.printStackTrace();
        }
        ConcurrentSkipListSet<AnObject> items = fetchAll.getItems();
        Iterator<AnObject> it = items.iterator();
        while (it.hasNext()) {
            // insert your cancellation logic here
            // ...
            AnObject daoObj = it.next();
            FetchOneTask fetchOne = new FetchOneTask(secondDao, daoObj.getId());
            Future<?> fetchOneFuture = pool.submit(fetchOne);
            try {
                fetchOneFuture.get();
                AnObject anotherDaoObj = fetchOne.getAnObject();
                if (anotherDaoObj == null) {
                    // the object retrievied by the first dao (first datasource)
                    // is not in the second; it needs to be inserted into the second
                    System.out.println(String.format("Inserting %s", daoObj));
                    secondDao.insert(daoObj);
                } else {
                    System.out.println(String.format("Updating %s to %s", anotherDaoObj, daoObj));
                    secondDao.update(daoObj);
                }
            } catch (Exception e) {
                System.out.println("An exception occurred!");
                e.printStackTrace();
            }
        }

        Set<AnObject> itemsInSecondDb = secondDao.fetchAll();
        for (AnObject o : itemsInSecondDb) {
            System.out.println(o);
        }

        pool.shutdown();
    }

    // ... invoke the app thread from somewhere else

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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