本文介绍了Java SwingWorker 从数据库加载数据到列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的 MVC 应用程序在 JTable 中显示数据时遇到问题.一切正常,但我决定添加一个 SwingWorker 来从数据库中检索数据.

I have a problem with my MVC application that displays data in a JTable. Everything worked fine, but I decided to add a SwingWorker to retrieve data from the database.

我的控制器使用数据库中的数据调用模型.它看起来像这样.

My controller calls the model with data from the database. It looks like this.

模型.java

    public class Model {

    private List<Category> people = new Vector<Category>();

    public List<Category> getPeople() {
        return new ArrayList<Category>(people);
    }

    public void load() throws Exception {
        people.clear();
        DAOFactory factory = DAOFactory.getFactory(DAOFactory.MYSQL);
        CategoryDAO personDAO = factory.getCategoryDAO();
        people.addAll(personDAO.getCategory());
    }

}

我将 SwingWorker 添加到 getCategory 类

I add SwingWorker to getCategory class

MySQLCategodyDAO.java

MySQLCategodyDAO.java

public class MySQLCategoryDAO extends SwingWorker<Void, Vector<Object>> implements CategoryDAO{

    private Job job;
    private List<Category> cat;

    public MySQLCategoryDAO(Job job){
        this.job = job;
    }

    @Override
    protected Void doInBackground() throws Exception {
        // TODO Auto-generated method stub

        if(job == Job.SELECT){
            getCategory();
            System.out.println("Table selected");
        }       
        return null;
    }   
    @Override()
    public void done(){


    }

    public List<Category> getCategory() throws SQLException
    {
        cat = new ArrayList<Category>();
        Connection conn = Database.getInstance().getConnection();

        System.out.println(conn);

        String sql = "select id, name from kategorie";
        Statement selectStatement =  conn.createStatement();

        ResultSet results = selectStatement.executeQuery(sql);

        while(results.next())
        {
            int id = results.getInt("id");
            String name = results.getString("name");

            Category category = new Category(id, name);
            cat.add(category);
        }

        results.close();
        selectStatement.close();

        return cat;

    }
}

View 只是从模型中检索数据:

View just retrieves the data from the model:

        people = model.getPeople();
        for (Category person : people) {
            tablemodel
                    .addRow(new Object[] { person.getId(), person.getName() });
        }

在 Model.java 类中调用 SwingWorker 时出现问题

The problem comes when you call SwingWorker in class Model.java

public void load() throws Exception {
    people.clear();
    DAOFactory factory = DAOFactory.getFactory(DAOFactory.MYSQL);
    CategoryDAO personDAO = factory.getCategoryDAO();
    people.addAll(new MySQLCategoryDAO(Job.SELECT).execute());  - ERROR
}

错误:-

The method addAll(Collection<? extends Category>) in the type List<Category> is not applicable for the 
     arguments (void)

我知道 SwingWorker 什么都不返回,因为有一个错误.我应该在方法 done() 中编写代码,但我不知道如何解决它.

I know SwingWorker returns nothing, because there is an error. I should write the code in the method done(), but I have no idea how to solve it.

推荐答案

execute 没有返回值,因此无法按照您尝试使用的方式使用它.SwingWorker 的想法是任务应该异步执行,所以你需要重新设计你的设计.

execute does not have a return value so it can't be used in the way you are trying to use it. The idea of SwingWorker is that the task should be executed asynchronously so you need to rework your design.

SwingWorker 产生一个结果(List),你要么需要:

The SwingWorker bears a result (the List<Category>) and you either need to:

  • 将结果放在 SwingWorker 内部的某个位置(例如使用发布机制)
  • 或者从外部调用get等待任务完成返回.
  • put the result somewhere from inside the SwingWorker (such as with the publish mechanism)
  • or call get from the outside to wait for the task to finish and return.

这里是复习教程:http://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html

快速示例:

class MySQLCategoryDAO extends SwingWorker<Void, Category> {

    // ...

    private List<Category> list; // do not modify inside doInBackground

    MySQLCategoryDAO(Job job, List<Category> list) {
        this.list = list;

        // ...
    }

    @Override
    protected Void doInBackground() {

        // ...

        while(results.next()) {
            int id = results.getInt("id");
            String name = results.getString("name");

            publish(new Category(id, name)); // publish results to the EDT
        }

        // ...

        return null;
    }

    @Override
    protected void process(List<Category> chunks) {
        list.addAll(chunks); // add results to the list on the EDT

        // add to the JTable (?)
    }
}

public void load() throws Exception {
    people.clear();
    DAOFactory factory = DAOFactory.getFactory(DAOFactory.MYSQL);
    CategoryDAO personDAO = factory.getCategoryDAO();

    // just execute
    new MySQLCategoryDAO(Job.SELECT, people).execute();
}

如果您想一次填充整个表格,那么您还可以在循环后发布一个列表,而不是一次发布一个类别.process 将接收一个带有单个元素的 List.

If you want to populate the entire table at once then you can also publish a List after the loop instead of one Category at a time. process would receive a List<List<Category>> with a singular element.

这篇关于Java SwingWorker 从数据库加载数据到列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-29 21:41