java - Vaadin:如何显示 MySQL 数据库中的数据?

标签 java mysql spring maven vaadin

我正在开发 Vaadin Flow(版本 14.1)应用程序,但遇到了这个问题,我无法将其直接与 MySQL 数据库连接。

我已经与 Maven 设置了 JDBC 连接,我还创建了一个名为 Datasource 的单例类,在其中存储我的值和方法。然而现在它只有一个,因为我正在测试它,这就是我想做的:

  • 点击应用上的按钮并更新标签

这是按钮点击监听器:

button.addClickListener(click -> {
        label.setText(Datasource.getInstance().getUsername());
    });

这是数据源类方法:

public String getUsername() {
    String username = "QUERY-FAILED";

    try {
        start();
        statement = conn.createStatement();
        ResultSet rs = statement.executeQuery("select * from names");

        rs.next();
        username = rs.getString(1);
    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        close();
    }

    return username;
}

但是标签不会更新,如果我注释 try block ,它会更新为 QUERY-FAILED,这是我用来测试是否失败的字符串,但如果没有注释,标签将保持不变。

我还尝试向 Datasource 类添加一个 main 方法并将其作为 Java 应用程序运行,该方法工作正常,它确实返回一个带有用户名的字符串。所以我猜我被困在与 vaadin 应用程序的连接之间。另外,如果我在启动应用程序时尝试在我的 vaadin 应用程序中获取用户名字符串(而不是使用单击监听器),我会收到一长串错误,其中数据源指示 nullpointerexception:

statement = conn.createStatement();

提前致谢!

最佳答案

我无法发现您的代码有任何问题。但我可以提供一个完整的工作示例应用程序供您比较

我的示例应用程序遵循您的问题代码中列出的路线。 Vaadin Button 使用用户名表中的 DataSource 对象执行数据库查询。找到的第一行的值显示在网页上的 Vaadin Label 小部件中。

enter image description here

此应用程序是使用 Vaadin 14.1.5 构建并运行的,使用了入门项目的“Plain Java Servlet”风格 provided by the Vaadin.com site 。使用捆绑的 Jetty Web 容器在 macOS Mojave 上运行。

我对其 Maven POM 文件的唯一更改是更改为 Java 版本 13,并添加 H2 Database Engine 的依赖项使其成为一个使用内存数据库的独立示例。

    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <version>1.4.200</version>
    </dependency>

我使用 Vaadin 启动的钩子(Hook)来建立我的 DataSource对象并初始化数据库。 Following the manual ,嵌套在 resources 文件夹中,我创建了文件夹 META-INF > services。根据 Java SPI设施中,我创建了一个名为 com.vaadin.flow.server.VaadinServiceInitListener 的文件,其中包含一行来指定实现此文件名称中指定的接口(interface)的类的名称:

work.basil.example.ApplicationServiceInitListener

也就是说,我的 ApplicationServiceInitListener 类实现 Vaadin 接口(interface) VaadinServiceInitListener。当我的 Vaadin Web 应用程序启动时,我的类将自动实例化,并通过 Java SPI 工具调用其方法。

我的ApplicationServiceInitListener类:

package work.basil.example;

import com.vaadin.flow.server.ServiceInitEvent;
import com.vaadin.flow.server.VaadinServiceInitListener;
import org.h2.jdbcx.JdbcDataSource;

public class ApplicationServiceInitListener implements VaadinServiceInitListener
{
    @Override
    public void serviceInit ( ServiceInitEvent serviceInitEvent )
    {
        System.out.println( "DEBUG Running `serviceInit` of " + this.getClass().getCanonicalName() );

        // Database work.
        prepareDataSource();
        App.INSTANCE.provideDatabase().initializeDatabase();
    }

    private void prepareDataSource ( )
    {
        JdbcDataSource ds = new JdbcDataSource();
        ds.setURL( "jdbc:h2:mem:demo;DB_CLOSE_DELAY=-1" );
        ds.setUser( "scott" );
        ds.setPassword( "tiger" );
        App.INSTANCE.rememberDataSource( ds );
    }
}

该类调用我的 App 类,该类充当某种 service locator 。设计为singleton通过 enum .

package work.basil.example;

import javax.sql.DataSource;
import java.util.Objects;

public enum App
{
    INSTANCE;

    // -------|  DataSource  |---------------------------------
    private DataSource dataSource;

    public DataSource provideDataSource ( )
    {
        return this.dataSource;
    }

    public void rememberDataSource ( DataSource dataSource )
    {
        this.dataSource = Objects.requireNonNull( dataSource );
    }


    // -------|  Database  |---------------------------------
    private Database database;

    public Database provideDatabase ( )
    {
        return new Database();
    }
}

该类调用我的Database 类。在实际工作中,数据库将是一个具有各种具体实现的接口(interface),用于测试与部署。为了演示目的,我在这里忽略了这一点。

package work.basil.example;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class Database
{
    public String getFirstUserName ( )
    {
        String userName = "QUERY-FAILED";

        String newline = "\n";
        StringBuilder sql = new StringBuilder();
        sql.append( "SELECT name_ from  user_ ; " ).append( newline );
        System.out.println( "sql = " + sql );
        try (
                Connection conn = App.INSTANCE.provideDataSource().getConnection() ;
                Statement statement = conn.createStatement() ;
                ResultSet resultSet = statement.executeQuery( sql.toString() ) ;
        )
        {
            while ( resultSet.next() )
            {
                userName = resultSet.getString( "name_" );
                break; // Go no further. We need only the first row found.
            }
        }
        catch ( SQLException e )
        {
            e.printStackTrace();
        }

        return userName;
    }

    public void initializeDatabase ( )
    {
        System.out.println( "DEBUG Running `initializeDatabase` of " + this.getClass().getCanonicalName() );
        String newline = "\n";

        // Create table.
        StringBuilder sql = new StringBuilder();
        sql.append( "CREATE TABLE user_ ( " ).append( newline );
        sql.append( "pkey_ IDENTITY NOT NULL PRIMARY KEY , " ).append( newline );  // `identity` = auto-incrementing long integer.
        sql.append( "name_ VARCHAR NOT NULL " ).append( newline );
        sql.append( ") " ).append( newline );
        sql.append( ";" ).append( newline );
        System.out.println( "sql = " + sql );
        try (
                Connection conn = App.INSTANCE.provideDataSource().getConnection() ;
                Statement statement = conn.createStatement() ;
        )
        {
            statement.executeUpdate( sql.toString() );
        }
        catch ( SQLException e )
        {
            e.printStackTrace();
        }
        System.out.println("DEBUG Finished `CREATE TABLE` statement.");

        // Populate table.
        sql = new StringBuilder();
        sql.append( "INSERT INTO user_ ( name_ ) " ).append( newline );
        sql.append( "VALUES " ).append( newline );
        sql.append( "( 'Alice' ) , " ).append( newline );
        sql.append( "( 'Bob' ) , " ).append( newline );
        sql.append( "( 'Carol' ) " ).append( newline );
        sql.append( ";" ).append( newline );
        System.out.println( "sql = " + sql );
        try (
                Connection conn = App.INSTANCE.provideDataSource().getConnection() ;
                Statement statement = conn.createStatement() ;
        )
        {
            int rowsAffected = statement.executeUpdate( sql.toString() );
            System.out.println( "DEBUG Inserted rows into name_ table: " + rowsAffected );
        }
        catch ( SQLException e )
        {
            e.printStackTrace();
        }
        System.out.println("DEBUG Finished `INSERT` statement.");
    }
}

最后是 MainView 类。我禁用了 @PWA 注释,因为我们没有将该功能用于渐进式 Web 应用程序。

package work.basil.example;

import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.html.Label;
import com.vaadin.flow.component.notification.Notification;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.router.Route;

/**
 * The main view contains a button and a click listener.
 */
@Route ( "" )
//@PWA ( name = "Project Base for Vaadin", shortName = "Project Base" )
public class MainView extends VerticalLayout
{
    private Label label;
    private Button button;

    public MainView ( )
    {
        // Widgets
        this.label = new Label( "User: ?" );
        this.button = new Button(
                "Get user" ,
                event -> {
                    Notification.show( "Getting user." );
                    String userName = App.INSTANCE.provideDatabase().getFirstUserName();
                    this.label.setText( "User: " + userName );
                }
        );
        add( button );

        // Arrange
        this.add( label , button );
    }
}

关于java - Vaadin:如何显示 MySQL 数据库中的数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59888643/

相关文章:

mysql - 仅当所有行都匹配时,SQL 连接才返回结果

php - 子查询在 MySQL Workbench 中工作,但在 PHP 中不工作

java - 如何在 spring 中禁用调试日志

java - 如何在java中使用EPOCH时间?

java - 今天的编程语言只允许一个方法返回值的原因是什么?

java - 除非添加验证返回,否则不会调用 iPOJO 组件注入(inject)回调

python - 将多个 CSV 字段导入一个 MySQL 字段

java - 更改添加到堆栈的变量的值而不更改堆栈?

java - 在 Form .java 文件中检索用于国际化的 Spring 外部化字符串

spring - 在 @SpringBootApplication 外部执行 CommandLineRunner