通过调用 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 ( )
{
}
}
生成测试数据时,我希望新行中的字段默认为 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 ( )
{
}
}