在JPA中,是否可以为列设置默认值?如果可以,使用注释应该如何实现?
你可以按照以下步骤进行操作:
@Column(name="price")
private double price = 0.0;
好的!你刚刚使用了零作为默认值。
请注意,如果你只从应用程序访问数据库,则这将对你有所帮助。如果其他应用程序也使用该数据库,则应该使用Cameron的columnDefinition注释属性或其他方式在数据库中进行此检查。
null
)会设置默认值。在我看来,使用 @PrePersist
和 @PreUpdate
是更好的选择。 - JaspercolumnDefinition
属性不是数据库无关的,而@PrePersist
在插入之前会覆盖您的设置。 "默认值"是另一回事,当未显式设置值时使用默认值。 - Utku Özdemir实际上在JPA中是有可能的,虽然需要使用@Column
注解的columnDefinition
属性来实现一个小技巧,例如:
@Column(name="Price", columnDefinition="Decimal(10,2) default '100.00'")
insertable=false
。这样做可以使内容更加易懂。 - eckes另一种方法是使用javax.persistence.PrePersist
@PrePersist
void preInsert() {
if (this.createdTime == null)
this.createdTime = new Date();
}
if (createdt != null) createdt = new Date();
或者其他类似的形式。现在这样写会覆盖明确给定的数值,这似乎不是真正的默认值。 - Max Nanasycreatedt
为空,则创建一个新的日期对象。 - Shanenull
检查。 - Ondra Žižka@Column(columnDefinition='...')
,您需要在其中放置列的文字SQL定义。这相当不灵活,并且强制您还要声明其他方面,例如类型,这会使JPA实现对此问题的看法被短路。@Column(length = 4096, nullable = false)
@org.hibernate.annotations.ColumnDefault("")
private String description;
通过 DDL 确定要应用于关联列的默认值。
有两点需要注意:
1)不要害怕使用非标准的方法。作为 JBoss 开发人员,我见过很多规范流程。规范基本上是给定领域中的大玩家愿意承诺支持下一个十年左右的基线。对于安全、消息传递、ORM 也是如此(虽然 JPA 已经涵盖了很多)。作为开发人员,我的经验是,在复杂的应用程序中,迟早会需要非标准的 API。而 @ColumnDefault
就是一个例子,它优于使用非标准解决方案的负面影响。
2)大家都喜欢在@PrePersist或构造函数成员初始化时挥手致意,这很好。但这不一样。那么批量SQL更新怎么办?有些语句不设置列怎么办?DEFAULT
有其作用,不能通过初始化Java类成员来替代它。
JPA不支持此功能,如果支持会更加有用。使用columnDefinition是特定于数据库的,而且在许多情况下是不可接受的。在类中设置默认值是不够的,因为当你检索包含null值的记录时(这通常发生在重新运行旧的DBUnit测试时),它不会生效。我所做的是:
public class MyObject
{
int attrib = 0;
/** Default is 0 */
@Column ( nullable = true )
public int getAttrib()
/** Falls to default = 0 when null */
public void setAttrib ( Integer attrib ) {
this.attrib = attrib == null ? 0 : attrib;
}
}
Java的自动装箱在这方面有很大帮助。
@Column(columnDefinition="tinyint(1) default 1")
我刚刚测试了这个问题。它完全正常工作。谢谢你的提示。
关于评论:
@Column(name="price")
private double price = 0.0;
这个并没有在数据库中设置默认列值(当然)。
既然我在谷歌上搜索同样的问题时偶然发现了这个,为了让其他人也能够受益,我会提供我想出的解决方案。
在我看来,对于这个问题实际上只有一种解决方案 - @PrePersist。如果你选择在@PrePersist中进行操作,那么你需要检查该值是否已经被设置。
@PrePersist
来解决 OP 的问题。@Column(columnDefinition=...)
看起来不太优雅。 - Piotr NowickicolumnDefinition
,它运行得非常好。@Column(columnDefinition="TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
private Date createdDate;
您可以使用Java反射API:
@PrePersist
void preInsert() {
PrePersistUtil.pre(this);
}
这是常见的:
public class PrePersistUtil {
private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
public static void pre(Object object){
try {
Field[] fields = object.getClass().getDeclaredFields();
for(Field field : fields){
field.setAccessible(true);
if (field.getType().getName().equals("java.lang.Long")
&& field.get(object) == null){
field.set(object,0L);
}else if (field.getType().getName().equals("java.lang.String")
&& field.get(object) == null){
field.set(object,"");
}else if (field.getType().getName().equals("java.util.Date")
&& field.get(object) == null){
field.set(object,sdf.parse("1900-01-01"));
}else if (field.getType().getName().equals("java.lang.Double")
&& field.get(object) == null){
field.set(object,0.0d);
}else if (field.getType().getName().equals("java.lang.Integer")
&& field.get(object) == null){
field.set(object,0);
}else if (field.getType().getName().equals("java.lang.Float")
&& field.get(object) == null){
field.set(object,0.0f);
}
}
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
}
}
}
Field[] fields = object.getClass().getDeclaredFields();
的代码放入for()
中。并且在参数/捕获异常中添加final
,以防止意外修改object
。还要添加一个对null
的检查:if (null == object) { throw new NullPointerException("Parameter 'object' is null"); }
。这确保了object.getClass()
是安全的调用,不会触发NPE
。原因是为了避免懒惰程序员的错误。;-) - Roland@Column(columnDefinition='...')
在插入数据时,如果你在数据库中设置默认约束条件,它就不起作用了。insertable = false
添加到注释中,并从注释中删除columnDefinition='...'
,然后数据库将自动从数据库中插入默认值。insertable = false
,它就能正常工作。
columnDefinition
或@ColumnDefault
,建议坚持使用标准类型。https://dba.stackexchange.com/questions/53317/databases-are-there-universal-datatypes. - Oliver