我无法发现您的代码有任何问题。但我可以提供一个完整的工作示例应用程序供您比较
我的示例应用程序遵循您的问题代码中列出的行。Vaadin使用用户名表中Button的对象执行数据库查询。DataSource找到的第一行的值显示在Label网页上的 Vaadin 小部件中。

这个应用程序是使用 Vaadin 14.1.5 构建和运行的,使用Vaadin.com 网站提供的“Plain Java Servlet”风格的入门项目。使用捆绑的 Jetty Web 容器在 macOS Mojave 上运行。
我对他们的 Maven POM 文件的唯一更改是更改为 Java 版本 13,并添加了对H2 数据库引擎的依赖项,以使其成为使用内存数据库的自包含示例。
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.200</version>
</dependency>
我使用启动 Vaadin 的钩子来建立我的DataSource对象并初始化数据库。按照手册,嵌套在resources文件夹中,我创建了文件夹META-INF> services。根据Java SPI工具,我在那里创建了一个名为的文件,com.vaadin.flow.server.VaadinServiceInitListener其中包含一行来指定我的类的名称,该类实现了以该文件的名称命名的接口:
work.basil.example.ApplicationServiceInitListener
也就是说,我的ApplicationServiceInitListener类实现了 Vaadin 接口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类,它充当一种服务定位器。通过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班。在实际工作中,Database将是一个具有各种具体实现的接口,用于测试与部署。出于演示目的,我在这里忽略了这一点。
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 );
}
}