MySQL DATETIME precision (joda-time, Hibernate, org.jadira.usertype, hbm2ddl)

萝らか妹 提交于 2019-12-06 02:31:22

问题


In my hibernate-4 entity, I am mapping a joda-time DateTime property using the recommended jadira usertypes:

@Entity
@Table(name="timing")
public class TimingEntity {
    ...
    @Basic(optional=false)
    @Column(name="moment")
    @Type(type="org.jadira.usertype.dateandtime.joda.PersistentDateTime")
    public DateTime getMoment() {
       ...

My database is MySQL. With hibernate property hbm2ddl.auto set to create value, I have the following column generated in my timing table:

CREATE TABLE `timing` (
    ...
   `moment` DATETIME NOT NULL,
    ...
)

The generated CREATE TABLE contains the DATETIME column. The DATETIME in MySQL has only seconds precision, without fractional part. In order to enable fractional part, up to microseconds, MySQL 5.6.4 and higher enables DATETIME(precision) columns, for example DATETIME(3) to have milliseconds precision.

My question is -- is there way to specify precision for my temporal fields generated with hbm2ddl? At least, is this a matter of jadira usertypes, or java.sql, or jdbc driver machinery?

P.S. When I manually modify the DB table to have the exact column precision I want, say, DATETIME(3), everything works OK - joda DateTimes are written and read from the DB with milliseconds precision.


回答1:


Use can use @Column#columnDefinition property for it

@Basic(optional=false)
@Column(name="moment" columnDefinition="DATETIME(3) NOT NULL")
@Type(type="org.jadira.usertype.dateandtime.joda.PersistentDateTime")
public DateTime getMoment() 
{   
   ...

Also you can try @Column#precision property, but in documentation is written that this working only for decimals.




回答2:


I've found one more solution that allows not to hardcode MySQL column definition snippet in your @Column annotation. Define your own hibernate dialect by overriding org.hibernate.dialect.MySQLDialect:

package org.yourproject;

import java.sql.Types;
import org.hibernate.dialect.MySQL5Dialect;

public class MySQL564PlusDialect extends MySQL5Dialect {
   public MySQL564PlusDialect() {
      super();
      registerColumnType( Types.TIMESTAMP, 6, "datetime($l)" );
   }
}

and specify it as hibernate property hibernate.dialect=org.yourproject.MySQL564PlusDialect (the dialect you'll want to extend may vary, e.g. org.hibernate.dialect.MySQL5InnoDBDialect instead).

Now you can adjust precision of your DATETIME from within @Column annotation by using length attribute:

@Basic(optional=false)
@Column(name="moment", length=3)
@Type(type="org.jadira.usertype.dateandtime.joda.PersistentDateTime")
public DateTime getMoment() {
 ...

which will produce DATETIME(3) column definition meaning milliseconds precision. If you need the simple DATETIME (no fractional seconds), just don't specify length. You can use value of length up to 6 which would mean microseconds precision.

If you happen to use a dialect different from the above one (for example the standard org.hibernate.dialect.MySQLDialect or maybe some other database), that will not break your code: the length attribute on @Column will be ignored.

P.S. It would be more sensible to exploit the precision attribute of @Column instead of length, but simple replacing of "datetime($l)" pattern with "datetime($p)" one in my own dialect implementation does not work offhand.



来源:https://stackoverflow.com/questions/22785117/mysql-datetime-precision-joda-time-hibernate-org-jadira-usertype-hbm2ddl

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!