通过调用 Java 方法为 H2 数据库中的新行生成默认值

Generate default values for new rows in H2 database by calling a Java method

生成测试数据时,我希望新行中的字段默认为 lorem, a Lorem Ipsum 生成器为 Java 生成的乱码值。

在 Java 中调用 lorem 工具如下所示:

 String lorem = LoremIpsum.getInstance().getWords( 100 , 120 );

我试过这个 SQL 作为我的 table 定义:

String sql =
        """
        CREATE ALIAS LOREM FOR "com.thedeanda.lorem.LoremIpsum.getInstance().getWords( 100 , 120 )";
        CREATE TABLE IF NOT EXISTS thing_
        (
            nonsense_ text NOT NULL  ,
            row_created_ TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP() ,
            id_ uuid NOT NULL DEFAULT RANDOM_UUID() ,
            CONSTRAINT thing_pkey_ PRIMARY KEY ( id_ )
        )
        ;
        """;

但是抛出:

org.h2.jdbc.JdbcSQLSyntaxErrorException: The public static Java method was not found: "getInstance().getWords(100,120) (com.thedeanda.lorem.LoremIpsum)"; SQL statement:

CREATE ALIAS LOREM FOR "com.thedeanda.lorem.LoremIpsum.getInstance().getWords( 100 , 120 )"; [90139-200]

是否有某种方法可以将对 Java 方法的调用包装起来,以用作 SQL 中 H2 的函数?

我认为您不能包含参数,也不能调用实例方法。您需要制作一个静态方法:

public class Whatever {
    public static String generateLorem() {
        return LoremIpsum.getInstance().getWords(100, 120);
    }
}

然后

CREATE ALIAS LOREM FOR "com.foo.Whatever.generateLorem";

正确。

此外,这是一个完整的示例应用程序,演示了该答案中的方法。

对于 运行 此代码,替换对 ds.setURL 的调用中的文件路径参数,以根据您的喜好命名和放置数据库文件。然后 运行 main 方法。

package work.basil.example;

import com.thedeanda.lorem.LoremIpsum;
import org.h2.jdbcx.JdbcDataSource;

import javax.sql.DataSource;
import java.sql.*;
import java.time.*;

import java.util.Objects;
import java.util.UUID;

public class FiftyMillion
{
    DataSource dataSource;


    public static String generateLorem ( )
    {
        return LoremIpsum.getInstance().getWords( 100 , 120 );
    }


    public static void main ( String[] args )
    {
        FiftyMillion app = new FiftyMillion();

        app.prepareDatabase();
        app.makeRow();
        app.dumpRows();
//        app.populateDatabase();
//        app.exportDatabaseToCsv();
    }

    // Constructor
    public FiftyMillion ( )
    {
        // DataSource
        org.h2.jdbcx.JdbcDataSource ds = Objects.requireNonNull( new JdbcDataSource() );  // Implementation of `DataSource` bundled with H2.
        ds.setURL( "jdbc:h2:/Volumes/blue_disc/fifty_million;" );
        ds.setUser( "scott" );
        ds.setPassword( "tiger" );
        ds.setDescription( "An example database showing ResultSet access to 50 million records." );
        this.dataSource = ds;
    }

    private void prepareDatabase ( )
    {
        String lorem = LoremIpsum.getInstance().getWords( 100 , 120 );
        String sql =
                """
                CREATE ALIAS IF NOT EXISTS LOREM FOR "work.basil.example.FiftyMillion.generateLorem" ;
                CREATE TABLE IF NOT EXISTS thing_
                (
                    nonsense_ text NOT NULL DEFAULT LOREM() ,
                    row_created_ TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP() ,
                    id_ uuid NOT NULL DEFAULT RANDOM_UUID() ,
                    CONSTRAINT thing_pkey_ PRIMARY KEY ( id_ )
                )
                ;
                """;
        try (
                Connection conn = dataSource.getConnection() ;
                Statement stmt = conn.createStatement() ;
        )
        {
            System.out.println( "INFO - Running `prepareDatabase` method." );
            stmt.executeUpdate( sql );
        }
        catch ( SQLException e )
        {
            e.printStackTrace();
        }
    }

    private void makeRow ( )
    {
        try
                (
                        Connection conn = this.dataSource.getConnection() ;
                        Statement stmt = conn.createStatement() ;
                )
        {
//            String lorem = LoremIpsum.getInstance().getWords( 100 , 120 );
            String sql =
                    """
                    INSERT INTO thing_ ()
                    VALUES ()
                    ;
                    """;
            stmt.executeUpdate( sql );
        }
        catch ( SQLException e )
        {
            e.printStackTrace();
        }
    }

    private void dumpRows ( )
    {
        try
                (
                        Connection conn = this.dataSource.getConnection() ;
                        Statement stmt = conn.createStatement() ;
                )
        {
            String sql =
                    """
                    TABLE thing_
                    ;
                    """;
            stmt.executeQuery( sql );
            ResultSet rs = stmt.executeQuery( sql );
            while ( rs.next() )
            {
                String nonsense = rs.getString( "nonsense_" );
                Instant whenCreated = rs.getObject( "row_created_" , OffsetDateTime.class ).toInstant();
                UUID id = rs.getObject( "id_" , UUID.class );
                System.out.println( "whenCreated = " + whenCreated + " | " + "id : " + id + " | " + "nonsense = " + nonsense );
            }
        }
        catch ( SQLException e )
        {
            e.printStackTrace();
        }
    }


    private void populateDatabase ( )
    {

    }

    private void exportDatabaseToCsv ( )
    {
    }

}