package com.zjrs.zwnw.config;

import com.fasterxml.jackson.datatype.hibernate5.Hibernate5Module;
import org.hibernate.dialect.Dialect;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Configuration
@EnableTransactionManagement
public class DatabaseConfiguration {

    /**
     * 通过<code>@Bean</code>注册，即可使用Spring-Boot的自动配置功能，当为SpringMVC的HttpMessageConverters注册一个
     * MappingJackson2HttpMessageConverter，其中的ObjectMapper将自动注册了Hibernate5Module模块。
     * <p>
     * Any beans of type com.fasterxml.jackson.databind.Module will be automatically registered with
     * the auto-configured Jackson2ObjectMapperBuilder and applied to any ObjectMapper instances that it creates.
     * This provides a global mechanism for contributing custom modules when you add new features to your application.
     * </p>
     * 自动注册的详情参看See Also
     * <p>
     * Hibernate5Module模块主要用于解决Jackson序列化带Hibernate注解的Entity，当Entity中包含有Lazy-Loading对象时，
     * 若Session已关闭不能加载，默认则序列化为null（可通过Feature配置）。
     * <br>
     * Hibernate5Module.Feature 枚举类型中定义了默认的模块配置。详细可参看源码。
     * </p>
     * 不建议使用"Open session in view"的解决方案，
     * <a href="https://vladmihalcea.com/2016/05/30/the-open-session-in-view-anti-pattern/">详细说明</a>
     *
     * @return Hibernate5Module实例
     * @see
     * <a href="http://docs.spring.io/spring-boot/docs/current/reference/html/howto-spring-mvc.html#howto-customize-the-jackson-objectmapper">Spring文档</a>
     */
    @Bean
    public Hibernate5Module hibernate5Module() {
        return new Hibernate5Module();
    }

    /**
     * 返回主要数据源的数据库Dialect，在某些JDBC场合可以灵活使用。
     */
    @Bean
    public Dialect primaryDialect(@Value("${spring.jpa.database-platform}") String databasePlatform)
        throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        return (Dialect) Class.forName(databasePlatform).newInstance();
    }
}
