GENERATED … AS IDENTITY
<>上>
H2 has recently swapped The non-standard IDENTITY
for the standard GENERATED BY DEFAULT AS IDENTITY
& GENERATED ALWAYS AS IDENTITY
syntax.
CREATE TABLE event_
(
pkey_ GENERATED ALWAYS AS IDENTITY PRIMARY KEY , -- Implicitly NOT NULL.
…
)
;
见<>。
IDENTITY
现代方法使用IDENTITY
,用于自动生成64-bit long integer。
This single-word syntax used in H2 is an abbreviated variation of GENERATED … AS IDENTITY
defined in the SQL:2003 standard. See summary in PDF document SQL:2003 Has Been Published. Other databases are implementing this, such as Postgres.
CREATE TABLE event_
(
pkey_ IDENTITY NOT NULL PRIMARY KEY , -- ⬅ `identity` = auto-incrementing long integer.
name_ VARCHAR NOT NULL ,
start_ TIMESTAMP WITH TIME ZONE NOT NULL ,
duration_ VARCHAR NOT NULL
)
;
例使用。 由于H2自动产生,无需通过我们<代码>pkey的栏值。
INSERT INTO event_ ( name_ , start_ , stop_ )
VALUES ( ? , ? , ? )
;
And Java.
ZoneId z = ZoneId.of( "America/Montreal" ) ;
OffsetDateTime start = ZonedDateTime.of( 2021 , Month.JANUARY , 23 , 19 , 0 , 0 , 0 , z ).toOffsetDateTime() ;
Duration duration = Duration.ofHours( 2 ) ;
myPreparedStatement.setString( 1 , "Java User Group" ) ;
myPreparedStatement.setObject( 2 , start ) ;
myPreparedStatement.setString( 3 , duration.toString() ) ;
Returning generated keys
Statement.RETURN_GENERATED_KEYS
你可以掌握在指挥执行期间所产生的价值。 需要两个步骤。 首先,通过旗帜。 收到你准备的发言。
PreparedStatement pstmt = conn.prepareStatement( sql , Statement.RETURN_GENERATED_KEYS ) ;
Statement::getGeneratedKeys
第二步是::Statement:GengeteratedKeys<> 在执行你准备的发言之后。 页: 1
Example app
Here is an entire example app. Running on Java 14 with Text Blocks preview feature enabled for fun. Using H2 version 1.4.200.
package work.basil.example;
import org.h2.jdbcx.JdbcDataSource;
import java.sql.*;
import java.time.*;
import java.util.Objects;
public class H2ExampleIdentity
{
public static void main ( String[] args )
{
H2ExampleIdentity app = new H2ExampleIdentity();
app.doIt();
}
private void doIt ( )
{
JdbcDataSource dataSource = Objects.requireNonNull( new JdbcDataSource() ); // Implementation of `DataSource` bundled with H2.
dataSource.setURL( "jdbc:h2:mem:h2_identity_example_db;DB_CLOSE_DELAY=-1" ); // Set `DB_CLOSE_DELAY` to `-1` to keep in-memory database in existence after connection closes.
dataSource.setUser( "scott" );
dataSource.setPassword( "tiger" );
String sql = null;
try (
Connection conn = dataSource.getConnection() ;
)
{
sql = """
CREATE TABLE event_
(
id_ IDENTITY NOT NULL PRIMARY KEY, -- ⬅ `identity` = auto-incrementing integer number.
title_ VARCHAR NOT NULL ,
start_ TIMESTAMP WITHOUT TIME ZONE NOT NULL ,
duration_ VARCHAR NOT NULL
)
;
""";
System.out.println( "sql:
" + sql );
try ( Statement stmt = conn.createStatement() ; )
{
stmt.execute( sql );
}
// Insert row.
sql = """
INSERT INTO event_ ( title_ , start_ , duration_ )
VALUES ( ? , ? , ? )
;
""";
try (
PreparedStatement pstmt = conn.prepareStatement( sql , Statement.RETURN_GENERATED_KEYS ) ;
)
{
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime start = ZonedDateTime.of( 2021 , 1 , 23 , 19 , 0 , 0 , 0 , z );
Duration duration = Duration.ofHours( 2 );
pstmt.setString( 1 , "Java User Group" );
pstmt.setObject( 2 , start.toOffsetDateTime() );
pstmt.setString( 3 , duration.toString() );
pstmt.executeUpdate();
try (
ResultSet rs = pstmt.getGeneratedKeys() ;
)
{
while ( rs.next() )
{
int id = rs.getInt( 1 );
System.out.println( "generated key: " + id );
}
}
}
// Query all.
sql = "SELECT * FROM event_ ;";
try (
Statement stmt = conn.createStatement() ;
ResultSet rs = stmt.executeQuery( sql ) ;
)
{
while ( rs.next() )
{
//Retrieve by column name
int id = rs.getInt( "id_" );
String title = rs.getString( "title_" );
OffsetDateTime odt = rs.getObject( "start_" , OffsetDateTime.class ); // Ditto, pass class for type-safety.
Instant instant = odt.toInstant(); // If you want to see the moment in UTC.
Duration duration = Duration.parse( rs.getString( "duration_" ) );
//Display values
ZoneId z = ZoneId.of( "America/Montreal" );
System.out.println( "id_" + id + " | start_: " + odt + " | duration: " + duration + " ➙ running from: " + odt.atZoneSameInstant( z ) + " to: " + odt.plus( duration ).atZoneSameInstant( z ) );
}
}
}
catch ( SQLException e )
{
e.printStackTrace();
}
}
}
其次,见结果。
Instant
, OffsetDateTime
, & ZonedDateTime
在执行时,我的证书制度目前的缺省区为。 在所储存的时刻(1月23日,2021日,魁北克省7 PM),该区<代码>America/Los_Angeles在8小时后从中央中央直辖区取冲抵。 因此,H2 JDBC驾驶员所交回的<代码>OffsetDatetime物体被打上<代码>-08:00的冲抵。 这是一种真实的区别,因此,在真正的工作中,我会立即将以下文字转换为:http://code>OffsetDatetime,要么将UTC的“Instant
,要么将“ZonedDatetime改为我所铭记的具体时间区。 很显然,<代码>Instant,OffsetDatetime
和ZonedDatetime
的物体均代表同一时间,即时间的相同点。 每次都在同一时刻通过不同的隔离墙时间看待。 加利福尼亚、魁北克和冰岛的3人(其区为美洲金枪鱼委,被抵消为零)在会议呼吁结束时发言,他们都在同一巧合的时刻看着各自隔离墙上的锁。
产生的关键: 1
id_1 ́start_: 2021-01-23T16:00-08:00 : PT2H ➙ 01: 2021-01-23T19:00-0 5 [America/Montreal] to: 2021-01-23T2
这样,在计算“future<>/em>任用书时,我们将在 Java和数据库中使用不同的数据类型。
我们将在 Java使用<条码>地方日<>和<条码>。 在数据库中,我们本来会使用类似于标准类别的数据类型。 TIMESTAMP withOUT TIM ZONE with a second section for the name of the aiming time area. 在从数据库中提取价值以建立时间表时,我们将将时间区适用于所储存的截止日期,以获得<编码>日代码>的物体。 这样,我们就可以在某一天预订任命,而不论该管辖区的政客对从中央直辖区被抵消的人有何变化。