我正在开发一个Spring(4.x)-Hibernate(5.2.x)Web应用程序项目。
模型类
@Entity
@Table( name = "users" )
public class User {
@Id
@Column( name="ID" )
@GeneratedValue( strategy = GenerationType.IDENTITY )
private Long id;
@Temporal( TemporalType.TIMESTAMP )
@Column( name="CREATED_AT", insertable=false, nullable=false )
@Generated( GenerationTime.INSERT )
private Date createdAt;
@Temporal( TemporalType.TIMESTAMP )
@Column( name="UPDATED_AT", insertable=false, updatable=false, nullable=false )
@Generated( GenerationTime.ALWAYS )
private Date updatedAt;
public enum Role {
ADMIN,
USER,
GUEST
}
@NotNull
@Column( name="ROLE" )
@Enumerated( EnumType.STRING )
private Role role;
//getters & setters
}
Hibernate属性
hibernate.dialect = org.hibernate.dialect.MySQLDialect
hibernate.show_sql = true
hibernate.format_sql = true
hibernate.hbm2ddl.auto = update
自动生成查询
create table users (
ID bigint not null auto_increment,
CREATED_AT datetime not null,
UPDATED_AT datetime not null,
ROLE varchar(255) not null,
primary key (id)
)
我希望查询
CREATED_AT DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
和UPDATED_AT DATETIME NOT NULL ON UPDATE CURRENT_TIMESTAMP
和ROLE ENUM('ADMIN','USER','GUEST') VARCHAR(255) NOT NULL
这是它的工作方式还是我在配置中的错误?完成了一些搜索,但没有找到明确的解决方案,除了这些,
@Column(name="CREATED_AT", nullable = false,columnDefinition="TIMESTAMP default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP")
@ColumnDefault( "NOW()" )
但是这些定义取决于底层数据库,这就是我的想法。需要一个更像java / hibernate的配置,就像我使用的那样,但不起作用!
答案 0 :(得分:2)
对于当前版本的jpa(休眠提供程序),
{
"settings": {
"x-powered-by": true,
"etag": "weak",
"env": "development",
"query parser": "extended",
"subdomain offset": 2,
"trust proxy": false,
"views": "/Users/filipeferminiano/MEGA/altcoin-site/views",
"jsonp callback name": "callback",
"view engine": "ejs"
},
"message": [],
"_locals": {},
"cache": false
}
标识DEFAULT值,以通过DDL(数据定义语言)应用于关联的列。
因此,似乎无法像预期的那样基于Java生成具有默认值的列的表
columnDefinition and @ColumnDefault
如果由于DDL语法可能不同,我们要切换到其他数据库服务器(oracle-> mysql),这将带来很多不便。但是jpa将来可能会具有此功能
解决方法针对您的问题,您必须对DDL使用默认值。
另一种方法,开发人员经常用来确保列始终在插入之前初始化。但这不会为数据库中的列生成默认值。
CREATED_AT DATETIME NOT NULL DEFAULT CURRENT_TIMESTAM
,如果其他开发人员使用本机sql查询,可能会失败。
如果找到其他解决方案并希望对您有所帮助,请更正!
答案 1 :(得分:2)
有一些方法可以解决您的问题。
P / s:您应该使用Flyway,Liquibase等数据库迁移工具。这些工具将为您带来很大帮助。
答案 2 :(得分:0)
DDL通常是特定于数据库的。要使用其他DDL,您可能需要研究Flyway,Liquibase等。
java / hibernate中的另一种方法是:
@Generated
已被改装为使用@ValueGenerationType
元注释。使用@ValueGenerationType
元注释 声明用于标记实体的自定义注释时 需要特定生成策略的属性。实际上 生成逻辑必须添加到实现AnnotationValueGeneration
界面。
如果需要在内存中生成时间戳记值,则必须使用以下映射:
实体:
@Entity(name = "Event")
public static class Event {
@Id
@GeneratedValue
private Long id;
@Column(name = "`timestamp`")
@FunctionCreationTimestamp
private Date timestamp;
//Constructors, getters, and setters are omitted for brevity
}
时间戳生成类:
@ValueGenerationType(generatedBy = FunctionCreationValueGeneration.class)
@Retention(RetentionPolicy.RUNTIME)
public @interface FunctionCreationTimestamp {}
public static class FunctionCreationValueGeneration
implements AnnotationValueGeneration<FunctionCreationTimestamp> {
@Override
public void initialize(FunctionCreationTimestamp annotation, Class<?> propertyType) {
}
/**
* Generate value on INSERT
* @return when to generate the value
*/
public GenerationTiming getGenerationTiming() {
return GenerationTiming.INSERT;
}
/**
* Returns the in-memory generated value
* @return {@code true}
*/
public ValueGenerator<?> getValueGenerator() {
return (session, owner) -> new Date( );
}
/**
* Returns false because the value is generated by the database.
* @return false
*/
public boolean referenceColumnInSql() {
return false;
}
/**
* Returns null because the value is generated in-memory.
* @return null
*/
public String getDatabaseGeneratedReferencedColumnValue() {
return null;
}
}
持久存储事件实体时,Hibernate生成以下SQL语句:
INSERT INTO Event ("timestamp", id)
VALUES ('Tue Mar 01 10:58:18 EET 2016', 1)
如您所见,new Date()
对象值用于分配时间戳记列值。
PS :(只是想想),您甚至可以使用if-else子句进行特定于数据库的实现。