hibernate.jdbc.time_zone = UTC被忽略

时间:2018-06-13 11:47:53

标签: java hibernate spring-boot timezone

使用设置为 Spring框架5.0.2.RELEASE Spring Security 5.0.0.RELEASE Hibernate 5.2.11.Final

我跟着spring boot& Vlad's link配置我的应用程序如下

db.properties -

jdbc.driverClassName = com.mysql.jdbc.Driver
jdbc.url = jdbc:mysql://hostname:port/appname?useSSL=false&serverTimezone=UTC&useLegacyDatetimeCode=false
jdbc.username = xxx
jdbc.password = xxx
jdbc.minPoolSize = 5
jdbc.maxPoolSize = 20
jdbc.maxIdleTime = 30000
hibernate.dialect = org.hibernate.dialect.MySQLDialect
hibernate.show_sql = true
hibernate.format_sql = false
spring.jpa.properties.hibernate.jdbc.time_zone = UTC

HibernateConfig.java

@Configuration
@EnableTransactionManagement
@ComponentScan(basePackages="in.greenstack.ikon")
@PropertySource(value = { "classpath:/resources/db.properties" })
public class HibernateConfig {

    @Autowired
    private Environment environment;

    @Bean(name = "myDataSource")
    ....

    @Bean
    public LocalSessionFactoryBean sessionFactory() {
        LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
        sessionFactory.setDataSource(dataSource());
        sessionFactory.setPackagesToScan(new String[] { "in.greenstack.ikon.entity" });
        sessionFactory.setHibernateProperties(hibernateProperties());
        return sessionFactory;
     }

    private Properties hibernateProperties() {
        Properties properties = new Properties();
        properties.put("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect"));
        properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql"));
        properties.put("hibernate.format_sql", environment.getRequiredProperty("hibernate.format_sql"));
        properties.put("spring.jpa.properties.hibernate.jdbc.time_zone", 
                environment.getRequiredProperty("spring.jpa.properties.hibernate.jdbc.time_zone"));
        return properties;        
   }

实体 -

@Entity
@Table(name = "PROJECT_MASTER")
public class Project {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID")
private int id;

@Column(name = "NAME")
private String name;

@Column(name = "START_DATE")
private Date startDate;

@Column(name = "END_DATE")
private Date endDate;

@ManyToOne
@JoinColumn(name = "FINANCIAL_YEAR")
private FinancialYear financialYear;

表定义 -

    CREATE TABLE `PROJECT_MASTER` (
    `ID` int(11) NOT NULL AUTO_INCREMENT,
  `NAME` varchar(50) NOT NULL,
  `FINANCIAL_YEAR` varchar(20) DEFAULT NULL,
  `START_DATE` date DEFAULT NULL,
  `END_DATE` date DEFAULT NULL,

日志 -

    2018-06-13 16:39:03 DEBUG SQL:92 - insert into PROJECT_MASTER (ACCOUNTING_STANDARD_ID, CONVERSION_METHOD_ID, CURRENCY_ID, DESCRIPTION, END_DATE, FINANCIAL_YEAR, HIERARCHY_ID, IMPORT_FROM_PREVIOUS, NAME, OPENING_PROJECT_ID, START_DATE) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: insert into PROJECT_MASTER (ACCOUNTING_STANDARD_ID, CONVERSION_METHOD_ID, CURRENCY_ID, DESCRIPTION, END_DATE, FINANCIAL_YEAR, HIERARCHY_ID, IMPORT_FROM_PREVIOUS, NAME, OPENING_PROJECT_ID, START_DATE) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
2018-06-13 16:39:03 TRACE ResourceRegistryStandardImpl:55 - Registering statement [com.mchange.v2.c3p0.impl.NewProxyPreparedStatement@747dab [wrapping: com.mysql.cj.jdbc.PreparedStatement@1abace9: insert into PROJECT_MASTER (ACCOUNTING_STANDARD_ID, CONVERSION_METHOD_ID, CURRENCY_ID, DESCRIPTION, END_DATE, FINANCIAL_YEAR, HIERARCHY_ID, IMPORT_FROM_PREVIOUS, NAME, OPENING_PROJECT_ID, START_DATE) values (** NOT SPECIFIED **, ** NOT SPECIFIED **, ** NOT SPECIFIED **, ** NOT SPECIFIED **, ** NOT SPECIFIED **, ** NOT SPECIFIED **, ** NOT SPECIFIED **, ** NOT SPECIFIED **, ** NOT SPECIFIED **, ** NOT SPECIFIED **, ** NOT SPECIFIED **)]]
2018-06-13 16:39:03 TRACE AbstractEntityPersister:2709 - Dehydrating entity: [in.greenstack.ikon.entity.Project#<null>]
2018-06-13 16:39:03 TRACE IdentifierValue:130 - ID unsaved-value: 0
2018-06-13 16:39:03 TRACE BasicBinder:65 - binding parameter [1] as [INTEGER] - [1]
2018-06-13 16:39:03 TRACE BasicBinder:53 - binding parameter [2] as [INTEGER] - [null]
2018-06-13 16:39:03 TRACE IdentifierValue:130 - ID unsaved-value: 0
2018-06-13 16:39:03 TRACE BasicBinder:65 - binding parameter [3] as [INTEGER] - [2]
2018-06-13 16:39:03 TRACE BasicBinder:65 - binding parameter [4] as [VARCHAR] - [TestTimeZone1 FY2017-2018 IGAAP]
**2018-06-13 16:39:03 TRACE BasicBinder:65 - binding parameter [5] as [DATE] - [2018-03-31]**
2018-06-13 16:39:03 TRACE IdentifierValue:130 - ID unsaved-value: 0
2018-06-13 16:39:03 TRACE BasicBinder:65 - binding parameter [6] as [INTEGER] - [2]
2018-06-13 16:39:03 TRACE BasicBinder:65 - binding parameter [7] as [INTEGER] - [30]
2018-06-13 16:39:03 TRACE BasicBinder:53 - binding parameter [8] as [BOOLEAN] - [null]
2018-06-13 16:39:03 TRACE BasicBinder:65 - binding parameter [9] as [VARCHAR] - [TestTimeZone1]
2018-06-13 16:39:03 TRACE BasicBinder:53 - binding parameter [10] as [INTEGER] - [null]
**2018-06-13 16:39:03 TRACE BasicBinder:65 - binding parameter [11] as [DATE] - [2017-04-01]**
2018-06-13 16:39:03 DEBUG IdentifierGeneratorHelper:78 - Natively generated identity: 63
2018-06-13 16:39:03 TRACE ResourceRegistryStandardImpl:91 - Releasing result set [com.mchange.v2.c3p0.impl.NewProxyResultSet@182014e [wrapping: com.mysql.cj.jdbc.result.ResultSetImpl@d243c6]]
2018-06-13 16:39:03 DEBUG ResourceRegistryStandardImpl:104 - HHH000387: ResultSet's statement was not registered
2018-06-13 16:39:03 TRACE ResourceRegistryStandardImpl:132 - Closing result set [com.mchange.v2.c3p0.impl.NewProxyResultSet@182014e [wrapping: com.mysql.cj.jdbc.result.ResultSetImpl@d243c6]]
2018-06-13 16:39:03 TRACE ResourceRegistryStandardImpl:68 - Releasing statement [com.mchange.v2.c3p0.impl.NewProxyPreparedStatement@747dab [wrapping: com.mysql.cj.jdbc.PreparedStatement@1abace9: **insert into PROJECT_MASTER (ACCOUNTING_STANDARD_ID, CONVERSION_METHOD_ID, CURRENCY_ID, DESCRIPTION, END_DATE, FINANCIAL_YEAR, HIERARCHY_ID, IMPORT_FROM_PREVIOUS, NAME, OPENING_PROJECT_ID, START_DATE) values (1, null, 2, 'TestTimeZone1 FY2017-2018 IGAAP', '2018-03-30', 2, 30, null, 'TestTimeZone1', null, '2017-03-31')]]**

从上面的日志中可以看出,绑定参数是从客户端发送的正确值(2017年4月1日和2018年3月31日),但在db中保存时仍然保存不正确的日期。

请提出我错过的建议。

pom.xml -

<properties>
        <spring.version>5.0.2.RELEASE</spring.version>
        <springsecurity.version>5.0.0.RELEASE</springsecurity.version>
        <mysql.connector.version>8.0.11</mysql.connector.version>
        <hibernate.version>5.2.17.Final</hibernate.version>
        <hibernate.validator.version>5.2.3.Final</hibernate.validator.version>
    </properties>

3 个答案:

答案 0 :(得分:4)

试试这个(它对我有用)。在spring boot主应用程序文件中写下以下代码片段。

@PostConstruct
public void started() {
    TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
}

Source

答案 1 :(得分:1)

改变这个:

 properties.put("spring.jpa.properties.hibernate.jdbc.time_zone", 
                environment.getRequiredProperty("spring.jpa.properties.hibernate.jdbc.time_zone"));

到此:

 properties.put("hibernate.jdbc.time_zone", 
            environment.getRequiredProperty("spring.jpa.properties.hibernate.jdbc.time_zone"));

答案 2 :(得分:1)

我认为您应该将spring.jpa.properties.hibernate.jdbc.time_zone = UTC放在application.ymlapplication.properties的{​​{1}} / main/中,而不要放在test/中。而且,我认为db.properties优先于.properties。如果我错了,请纠正我。

而且,此时区配置也受到.yml的影响。

查看此信息:https://aboullaite.me/spring-boot-time-zone-configuration-using-hibernate/

而且,正如我测试的那样,我看到如果您要保存一个本身没有时区信息的Timezone.getDefault()(仅在其java.util.Date属性中为true)和该列定义不保留时区信息,此属性将影响保存到数据库的值,但是不会,当您从数据库中检索行时,该属性不会起作用。后者仅受Calendar影响。同时,如果您设置Timezone.getDefault(),则已保存已检索值都是您想要的时区。

因此,如果您保存查询同一应用程序中的信息,则此属性可能不是操纵Date值的最合适方法。只需使用Timezone.getDefault()