Java SwingWorker 将数据从数据库加载到 List

Posted

技术标签:

【中文标题】Java SwingWorker 将数据从数据库加载到 List【英文标题】:Java SwingWorker load data from database to List 【发布时间】:2014-08-17 15:58:46 【问题描述】:

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

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

模型.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 类

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 只是从模型中检索数据:

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

当你在类 Model.java 中调用 SwingWorker 时,问题就来了

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()中编写代码,但我不知道如何解决它。

【问题讨论】:

【参考方案1】:

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

SwingWorker 产生结果(List&lt;Category&gt;),您需要:

将结果放在 SwingWorker 内部的某个位置(例如使用发布机制) 或从外部调用get等待任务完成并返回。

这里是复习教程: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&lt;List&lt;Category&gt;&gt;

【讨论】:

好的。谢谢它有效,但在视图中people = model.getPeople(); 为空。 我可以从 View 访问什么private List&lt;Category&gt; list; 你在 SwingWorker 中不访问私有 List,你传入一个 List 进行修改,然后从Model#getPeople 访问。或者至少在我的示例中就是这样。如果 getPeople 返回 null 那么您的代码与您在问题中显示的不同。 return new ArrayList&lt;Category&gt;(people); 永远不会返回 null。 好的。当我调用函数 getPeople() - Model.java 时,我没有得到任何数据。调用视图中的函数model.getPeople() 好的,可能是 Category 类或数据库的问题。我很难从远处猜测。如果它以前有效,请并排比较代码,以便您了解有什么不同。【参考方案2】:

对不起,我的错误。 从视图获取到 model.getPeople(),但没有返回任何内容。我做了一个测试:

但是什么都没有返回

 public class Model 

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

        public List<Category> getPeople() 

            for (Category person : people) 
                System.out.println(person.getName()); //no data
            
            return new ArrayList<Category>(people);
        
    public void load() throws Exception 
    people.clear();
    DAOFactory factory = DAOFactory.getFactory(DAOFactory.MYSQL);

    new MySQLCategoryDAO(Job.SELECT,people).execute();


【讨论】:

以上是关于Java SwingWorker 将数据从数据库加载到 List的主要内容,如果未能解决你的问题,请参考以下文章

Java - 如何将 JProgressBar 与 SwingWorker 一起使用

Java中的SwingWorker [关闭]

java swingworker线程更新main Gui

JAVA怎么定时自动画图

java - JLabel setForeground 在 SwingWorker 中不起作用

java遇到的问题及解答