美文网首页Kotlin Server
第16章 Spring Boot + Kotlin: 下一代 J

第16章 Spring Boot + Kotlin: 下一代 J

作者: 光剑书架上的书 | 来源:发表于2017-11-22 10:41 被阅读207次

    第16章 Spring Boot + Kotlin: 下一代 Java 服务端开发

    16.1 Kotlin 简介

    16.2 Kotlin 与 Java 的无缝集成

    16.3 Spring Boot 集成 Kotlin 开发实例详解

    image.png image.png image.png image.png

    Nextj2eeApplication.kt

    package com.kotlin.springboot.nextj2ee
    
    import org.springframework.boot.autoconfigure.SpringBootApplication
    import org.springframework.boot.runApplication
    
    @SpringBootApplication
    class Nextj2eeApplication
    
    fun main(args: Array<String>) {
        runApplication<Nextj2eeApplication>(*args)
    }
    
    

    build.gradle

    buildscript {
        ext {
            kotlinVersion = '1.1.60'
            springBootVersion = '2.0.0.M6'
        }
        repositories {
            mavenCentral()
            maven { url "https://repo.spring.io/snapshot" }
            maven { url "https://repo.spring.io/milestone" }
        }
        dependencies {
            classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
            classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}")
            classpath("org.jetbrains.kotlin:kotlin-allopen:${kotlinVersion}")
        }
    }
    
    apply plugin: 'kotlin'
    apply plugin: 'kotlin-spring'
    apply plugin: 'eclipse'
    apply plugin: 'org.springframework.boot'
    apply plugin: 'io.spring.dependency-management'
    
    group = 'com.kotlin.springboot'
    version = '0.0.1-SNAPSHOT'
    sourceCompatibility = 1.8
    compileKotlin {
        kotlinOptions.jvmTarget = "1.8"
    }
    compileTestKotlin {
        kotlinOptions.jvmTarget = "1.8"
    }
    
    repositories {
        mavenCentral()
        maven { url "https://repo.spring.io/snapshot" }
        maven { url "https://repo.spring.io/milestone" }
    }
    
    
    dependencies {
        compile('org.springframework.boot:spring-boot-starter-data-jpa')
        compile('org.springframework.boot:spring-boot-starter-freemarker')
        compile('org.springframework.boot:spring-boot-starter-web')
        compile("org.jetbrains.kotlin:kotlin-stdlib-jre8")
        compile("org.jetbrains.kotlin:kotlin-reflect")
        runtime('mysql:mysql-connector-java')
        testCompile('org.springframework.boot:spring-boot-starter-test')
    }
    
    
    Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaConfiguration': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Hikari.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.zaxxer.hikari.HikariDataSource]: Factory method 'dataSource' threw exception; nested exception is org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException: Cannot determine embedded database driver class for database type NONE. If you want an embedded database please put a supported one on the classpath. If you have database settings to be loaded from a particular profile you may need to active it (no profiles are currently active).
    2017-11-22 10:42:57.949  INFO 13877 --- [           main] o.apache.catalina.core.StandardService   : Stopping service [Tomcat]
    2017-11-22 10:42:58.000  INFO 13877 --- [           main] utoConfigurationReportLoggingInitializer : 
    
    Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled.
    2017-11-22 10:42:58.004 ERROR 13877 --- [           main] o.s.b.d.LoggingFailureAnalysisReporter   : 
    
    ***************************
    APPLICATION FAILED TO START
    ***************************
    
    Description:
    
    Cannot determine embedded database driver class for database type NONE
    
    Action:
    
    If you want an embedded database please put a supported one on the classpath. If you have database settings to be loaded from a particular profile you may need to active it (no profiles are currently active).
    
    
    Process finished with exit code 1
    

    BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Hikari.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.zaxxer.hikari.HikariDataSource]: Factory method 'dataSource' threw exception; nested exception is org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException: Cannot determine embedded database driver class for database type NONE. If you want an embedded database please put a supported one on the classpath. If you have database settings to be loaded from a particular profile you may need to active it (no profiles are currently active).

    Database dataSource Config

    2017-11-22 11:26:24.961  INFO 14423 --- [           main] com.zaxxer.hikari.HikariDataSource       : testdb - Starting...
    2017-11-22 11:26:25.306  INFO 14423 --- [           main] com.zaxxer.hikari.HikariDataSource       : testdb - Start completed.
    2017-11-22 11:26:25.373  INFO 14423 --- [           main] j.LocalContainerEntityManagerFactoryBean : Building JPA container EntityManagerFactory for persistence unit 'default'
    2017-11-22 11:26:25.385  INFO 14423 --- [           main] o.hibernate.jpa.internal.util.LogHelper  : HHH000204: Processing PersistenceUnitInfo [
        name: default
        ...]
    2017-11-22 11:26:25.481  INFO 14423 --- [           main] org.hibernate.Version                    : HHH000412: Hibernate Core {5.2.12.Final}
    2017-11-22 11:26:25.485  INFO 14423 --- [           main] org.hibernate.cfg.Environment            : HHH000206: hibernate.properties not found
    2017-11-22 11:26:25.544  INFO 14423 --- [           main] o.hibernate.annotations.common.Version   : HCANN000001: Hibernate Commons Annotations {5.0.1.Final}
    2017-11-22 11:26:25.738  INFO 14423 --- [           main] org.hibernate.dialect.Dialect            : HHH000400: Using dialect: org.hibernate.dialect.MySQL5Dialect
    2017-11-22 11:26:26.020  INFO 14423 --- [           main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
    

    hibernate.properties

    #
    # Hibernate, Relational Persistence for Idiomatic Java
    # org.hibernate.cfg.AvailableSettings
    #
    # License: GNU Lesser General Public License (LGPL), version 2.1 or later.
    # See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
    #
    ######################
    ### Query Language ###
    ######################
    ## define query language constants / function names
    #hibernate.query.substitutions yes 'Y', no 'N'
    ## select the classic query parser
    #hibernate.query.factory_class org.hibernate.hql.internal.classic.ClassicQueryTranslatorFactory
    #################
    ### Platforms ###
    #################
    ## JNDI Datasource
    #hibernate.connection.datasource jdbc/test
    #hibernate.connection.username db2
    #hibernate.connection.password db2
    ## HypersonicSQL
    #hibernate.dialect org.hibernate.dialect.HSQLDialect
    #hibernate.connection.driver_class org.hsqldb.jdbcDriver
    #hibernate.connection.username sa
    #hibernate.connection.password
    #hibernate.connection.url jdbc:hsqldb:./build/db/hsqldb/hibernate
    #hibernate.connection.url jdbc:hsqldb:hsql://localhost
    #hibernate.connection.url jdbc:hsqldb:test
    ## H2 (www.h2database.com)
    #hibernate.dialect org.hibernate.dialect.H2Dialect
    #hibernate.connection.driver_class org.h2.Driver
    #hibernate.connection.username sa
    #hibernate.connection.password
    #hibernate.connection.url jdbc:h2:mem:./build/db/h2/hibernate
    #hibernate.connection.url jdbc:h2:testdb/h2test
    #hibernate.connection.url jdbc:h2:mem:imdb1
    #hibernate.connection.url jdbc:h2:tcp://dbserv:8084/sample;
    #hibernate.connection.url jdbc:h2:ssl://secureserv:8085/sample;
    #hibernate.connection.url jdbc:h2:ssl://secureserv/testdb;cipher=AES
    ## MySQL
    hibernate.dialect org.hibernate.dialect.MySQLDialect
    #hibernate.dialect org.hibernate.dialect.MySQLInnoDBDialect
    #hibernate.dialect org.hibernate.dialect.MySQLMyISAMDialect
    hibernate.connection.driver_class com.mysql.jdbc.Driver
    #hibernate.connection.url jdbc:mysql:///test
    #hibernate.connection.username gavin
    #hibernate.connection.password
    ## Oracle
    #hibernate.dialect org.hibernate.dialect.Oracle8iDialect
    #hibernate.dialect org.hibernate.dialect.Oracle9iDialect
    #hibernate.dialect org.hibernate.dialect.Oracle10gDialect
    #hibernate.connection.driver_class oracle.jdbc.driver.OracleDriver
    #hibernate.connection.username ora
    #hibernate.connection.password ora
    #hibernate.connection.url jdbc:oracle:thin:@localhost:1521:orcl
    #hibernate.connection.url jdbc:oracle:thin:@localhost:1522:XE
    ## PostgreSQL
    #hibernate.dialect org.hibernate.dialect.PostgreSQLDialect
    #hibernate.connection.driver_class org.postgresql.Driver
    #hibernate.connection.url jdbc:postgresql:template1
    #hibernate.connection.username pg
    #hibernate.connection.password
    ## DB2
    #hibernate.dialect org.hibernate.dialect.DB2Dialect
    #hibernate.connection.driver_class com.ibm.db2.jcc.DB2Driver
    #hibernate.connection.driver_class COM.ibm.db2.jdbc.app.DB2Driver
    #hibernate.connection.url jdbc:db2://localhost:50000/somename
    #hibernate.connection.url jdbc:db2:somename
    #hibernate.connection.username db2
    #hibernate.connection.password db2
    ## TimesTen
    #hibernate.dialect org.hibernate.dialect.TimesTenDialect
    #hibernate.connection.driver_class com.timesten.jdbc.TimesTenDriver
    #hibernate.connection.url jdbc:timesten:direct:test
    #hibernate.connection.username
    #hibernate.connection.password
    ## DB2/400
    #hibernate.dialect org.hibernate.dialect.DB2400Dialect
    #hibernate.connection.username user
    #hibernate.connection.password password
    ## Native driver
    #hibernate.connection.driver_class COM.ibm.db2.jdbc.app.DB2Driver
    #hibernate.connection.url jdbc:db2://systemname
    ## Toolbox driver
    #hibernate.connection.driver_class com.ibm.as400.access.AS400JDBCDriver
    #hibernate.connection.url jdbc:as400://systemname
    ## Derby (not supported!)
    #hibernate.dialect org.hibernate.dialect.DerbyDialect
    #hibernate.connection.driver_class org.apache.derby.jdbc.EmbeddedDriver
    #hibernate.connection.username
    #hibernate.connection.password
    #hibernate.connection.url jdbc:derby:build/db/derby/hibernate;create=true
    ## Sybase
    #hibernate.dialect org.hibernate.dialect.SybaseDialect
    #hibernate.connection.driver_class com.sybase.jdbc2.jdbc.SybDriver
    #hibernate.connection.username sa
    #hibernate.connection.password sasasa
    #hibernate.connection.url jdbc:sybase:Tds:co3061835-a:5000/tempdb
    ## Mckoi SQL
    #hibernate.dialect org.hibernate.dialect.MckoiDialect
    #hibernate.connection.driver_class com.mckoi.JDBCDriver
    #hibernate.connection.url jdbc:mckoi:///
    #hibernate.connection.url jdbc:mckoi:local://C:/mckoi1.0.3/db.conf
    #hibernate.connection.username admin
    #hibernate.connection.password nimda
    ## SAP DB
    #hibernate.dialect org.hibernate.dialect.SAPDBDialect
    #hibernate.connection.driver_class com.sap.dbtech.jdbc.DriverSapDB
    #hibernate.connection.url jdbc:sapdb://localhost/TST
    #hibernate.connection.username TEST
    #hibernate.connection.password TEST
    #hibernate.query.substitutions yes 'Y', no 'N'
    ## MS SQL Server
    #hibernate.dialect org.hibernate.dialect.SQLServerDialect
    #hibernate.connection.username sa
    #hibernate.connection.password sa
    ## JSQL Driver
    #hibernate.connection.driver_class com.jnetdirect.jsql.JSQLDriver
    #hibernate.connection.url jdbc:JSQLConnect://1E1/test
    ## JTURBO Driver
    #hibernate.connection.driver_class com.newatlanta.jturbo.driver.Driver
    #hibernate.connection.url jdbc:JTurbo://1E1:1433/test
    ## WebLogic Driver
    #hibernate.connection.driver_class weblogic.jdbc.mssqlserver4.Driver
    #hibernate.connection.url jdbc:weblogic:mssqlserver4:1E1:1433
    ## Microsoft Driver (not recommended!)
    #hibernate.connection.driver_class com.microsoft.jdbc.sqlserver.SQLServerDriver
    #hibernate.connection.url jdbc:microsoft:sqlserver://1E1;DatabaseName=test;SelectMethod=cursor
    ## The New Microsoft Driver
    #hibernate.connection.driver_class com.microsoft.sqlserver.jdbc.SQLServerDriver
    #hibernate.connection.url jdbc:sqlserver://localhost
    ## jTDS (since version 0.9)
    #hibernate.connection.driver_class net.sourceforge.jtds.jdbc.Driver
    #hibernate.connection.url jdbc:jtds:sqlserver://1E1/test
    ## Interbase
    #hibernate.dialect org.hibernate.dialect.InterbaseDialect
    #hibernate.connection.username sysdba
    #hibernate.connection.password masterkey
    ## DO NOT specify hibernate.connection.sqlDialect
    ## InterClient
    #hibernate.connection.driver_class interbase.interclient.Driver
    #hibernate.connection.url jdbc:interbase://localhost:3060/C:/firebird/test.gdb
    ## Pure Java
    #hibernate.connection.driver_class org.firebirdsql.jdbc.FBDriver
    #hibernate.connection.url jdbc:firebirdsql:localhost/3050:/firebird/test.gdb
    ## Pointbase
    #hibernate.dialect org.hibernate.dialect.PointbaseDialect
    #hibernate.connection.driver_class com.pointbase.jdbc.jdbcUniversalDriver
    #hibernate.connection.url jdbc:pointbase:embedded:sample
    #hibernate.connection.username PBPUBLIC
    #hibernate.connection.password PBPUBLIC
    ## Ingres
    ## older versions (before Ingress 2006)
    #hibernate.dialect org.hibernate.dialect.IngresDialect
    #hibernate.connection.driver_class ca.edbc.jdbc.EdbcDriver
    #hibernate.connection.url jdbc:edbc://localhost:II7/database
    #hibernate.connection.username user
    #hibernate.connection.password password
    ## Ingres 2006 or later
    #hibernate.dialect org.hibernate.dialect.IngresDialect
    #hibernate.connection.driver_class com.ingres.jdbc.IngresDriver
    #hibernate.connection.url jdbc:ingres://localhost:II7/database;CURSOR=READONLY;auto=multi
    #hibernate.connection.username user
    #hibernate.connection.password password
    ## Mimer SQL
    #hibernate.dialect org.hibernate.dialect.MimerSQLDialect
    #hibernate.connection.driver_class com.mimer.jdbc.Driver
    #hibernate.connection.url jdbc:mimer:multi1
    #hibernate.connection.username hibernate
    #hibernate.connection.password hibernate
    ## InterSystems Cache
    #hibernate.dialect org.hibernate.dialect.Cache71Dialect
    #hibernate.connection.driver_class com.intersys.jdbc.CacheDriver
    #hibernate.connection.username _SYSTEM
    #hibernate.connection.password SYS
    #hibernate.connection.url jdbc:Cache://127.0.0.1:1972/HIBERNATE
    #################################
    ### Hibernate Connection Pool ###
    #################################
    hibernate.connection.pool_size 1
    ###########################
    ### C3P0 Connection Pool###
    ###########################
    #hibernate.c3p0.max_size 2
    #hibernate.c3p0.min_size 2
    #hibernate.c3p0.timeout 5000
    #hibernate.c3p0.max_statements 100
    #hibernate.c3p0.idle_test_period 3000
    #hibernate.c3p0.acquire_increment 2
    #hibernate.c3p0.validate false
    ##############################
    ### Proxool Connection Pool###
    ##############################
    ## Properties for external configuration of Proxool
    #hibernate.proxool.pool_alias pool1
    ## Only need one of the following
    #hibernate.proxool.existing_pool true
    #hibernate.proxool.xml proxool.xml
    #hibernate.proxool.properties proxool.properties
    #################################
    ### Plugin ConnectionProvider ###
    #################################
    ## use a custom ConnectionProvider (if not set, Hibernate will choose a built-in ConnectionProvider using hueristics)
    #hibernate.connection.provider_class org.hibernate.connection.DriverManagerConnectionProvider
    #hibernate.connection.provider_class org.hibernate.connection.DatasourceConnectionProvider
    #hibernate.connection.provider_class org.hibernate.connection.C3P0ConnectionProvider
    #hibernate.connection.provider_class org.hibernate.connection.ProxoolConnectionProvider
    #######################
    ### Transaction API ###
    #######################
    ## Enable automatic flush during the JTA beforeCompletion() callback
    ## (This setting is relevant with or without the Transaction API)
    #hibernate.transaction.flush_before_completion
    ## Enable automatic session close at the end of transaction
    ## (This setting is relevant with or without the Transaction API)
    #hibernate.transaction.auto_close_session
    ## the Transaction API abstracts application code from the underlying JTA or JDBC transactions
    #hibernate.transaction.factory_class org.hibernate.transaction.JTATransactionFactory
    #hibernate.transaction.factory_class org.hibernate.transaction.JDBCTransactionFactory
    ## to use JTATransactionFactory, Hibernate must be able to locate the UserTransaction in JNDI
    ## default is java:comp/UserTransaction
    ## you do NOT need this setting if you specify hibernate.transaction.manager_lookup_class
    #jta.UserTransaction jta/usertransaction
    #jta.UserTransaction javax.transaction.UserTransaction
    #jta.UserTransaction UserTransaction
    ## to use the second-level cache with JTA, Hibernate must be able to obtain the JTA TransactionManager
    #hibernate.transaction.manager_lookup_class org.hibernate.transaction.JBossTransactionManagerLookup
    #hibernate.transaction.manager_lookup_class org.hibernate.transaction.WeblogicTransactionManagerLookup
    #hibernate.transaction.manager_lookup_class org.hibernate.transaction.WebSphereTransactionManagerLookup
    #hibernate.transaction.manager_lookup_class org.hibernate.transaction.OrionTransactionManagerLookup
    #hibernate.transaction.manager_lookup_class org.hibernate.transaction.ResinTransactionManagerLookup
    ##############################
    ### Miscellaneous Settings ###
    ##############################
    ## print all generated SQL to the console
    #hibernate.show_sql true
    ## format SQL in log and console
    hibernate.format_sql true
    ## add comments to the generated SQL
    #hibernate.use_sql_comments true
    ## generate statistics
    #hibernate.generate_statistics true
    ## auto schema export
    #hibernate.hbm2ddl.auto create-drop
    #hibernate.hbm2ddl.auto create
    #hibernate.hbm2ddl.auto update
    #hibernate.hbm2ddl.auto validate
    ## specify a default schema and catalog for unqualified tablenames
    #hibernate.default_schema test
    #hibernate.default_catalog test
    ## enable ordering of SQL UPDATEs by primary key
    #hibernate.order_updates true
    ## set the maximum depth of the outer join fetch tree
    hibernate.max_fetch_depth 1
    ## set the default batch size for batch fetching
    #hibernate.default_batch_fetch_size 8
    ## rollback generated identifier values of deleted entities to default values
    #hibernate.use_identifier_rollback true
    ## enable bytecode reflection optimizer (disabled by default)
    #hibernate.bytecode.use_reflection_optimizer true
    #####################
    ### JDBC Settings ###
    #####################
    ## specify a JDBC isolation level
    #hibernate.connection.isolation 4
    ## enable JDBC autocommit (not recommended!)
    #hibernate.connection.autocommit true
    ## set the JDBC fetch size
    #hibernate.jdbc.fetch_size 25
    ## set the maximum JDBC 2 batch size (a nonzero value enables batching)
    #hibernate.jdbc.batch_size 5
    #hibernate.jdbc.batch_size 0
    ## enable batch updates even for versioned data
    #hibernate.jdbc.batch_versioned_data true
    ## enable use of JDBC 2 scrollable ResultSets (specifying a Dialect will cause Hibernate to use a sensible default)
    #hibernate.jdbc.use_scrollable_resultset true
    ## use streams when writing binary types to / from JDBC
    #hibernate.jdbc.use_streams_for_binary true
    ## use JDBC 3 PreparedStatement.getGeneratedKeys() to get the identifier of an inserted row
    #hibernate.jdbc.use_get_generated_keys false
    ## choose a custom JDBC batcher
    # hibernate.jdbc.factory_class
    ## enable JDBC result set column alias caching
    ## (minor performance enhancement for broken JDBC drivers)
    # hibernate.jdbc.wrap_result_sets
    ## choose a custom SQL exception converter
    #hibernate.jdbc.sql_exception_converter
    ##########################
    ### Second-level Cache ###
    ##########################
    ## optimize cache for minimal "puts" instead of minimal "gets" (good for clustered cache)
    #hibernate.cache.use_minimal_puts true
    ## set a prefix for cache region names
    #hibernate.cache.region_prefix hibernate.test
    ## disable the second-level cache
    #hibernate.cache.use_second_level_cache false
    ## enable the query cache
    #hibernate.cache.use_query_cache true
    ## store the second-level cache entries in a more human-friendly format
    #hibernate.cache.use_structured_entries true
    ## choose a cache implementation
    #hibernate.cache.region.factory_class org.hibernate.cache.infinispan.InfinispanRegionFactory
    #hibernate.cache.region.factory_class org.hibernate.cache.infinispan.JndiInfinispanRegionFactory
    #hibernate.cache.region.factory_class org.hibernate.cache.internal.EhCacheRegionFactory
    #hibernate.cache.region.factory_class org.hibernate.cache.internal.SingletonEhCacheRegionFactory
    #hibernate.cache.region.factory_class org.hibernate.cache.internal.NoCachingRegionFactory
    ## choose a custom query cache implementation
    #hibernate.cache.query_cache_factory
    ############
    ### JNDI ###
    ############
    ## specify a JNDI name for the SessionFactory
    #hibernate.session_factory_name hibernate/session_factory
    ## Hibernate uses JNDI to bind a name to a SessionFactory and to look up the JTA UserTransaction;
    ## if hibernate.jndi.* are not specified, Hibernate will use the default InitialContext() which
    ## is the best approach in an application server
    #file system
    #hibernate.jndi.class com.sun.jndi.fscontext.RefFSContextFactory
    #hibernate.jndi.url file:/
    #WebSphere
    #hibernate.jndi.class com.ibm.websphere.naming.WsnInitialContextFactory
    #hibernate.jndi.url iiop://localhost:900/
    
    

    2017-11-22 11:55:17.205 INFO 14721 --- [ main] org.hibernate.Version : HHH000412: Hibernate Core {5.2.12.Final}
    2017-11-22 11:55:17.208 INFO 14721 --- [ main] org.hibernate.cfg.Environment : HHH000205: Loaded properties from resource hibernate.properties: {hibernate.connection.driver_class=com.mysql.jdbc.Driver, hibernate.format_sql=true, hibernate.dialect=org.hibernate.dialect.MySQLDialect, hibernate.bytecode.use_reflection_optimizer=false, hibernate.max_fetch_depth=1, hibernate.connection.pool_size=1}
    2017-11-22 11:55:17.261 INFO 14721 --- [ main] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.0.1.Final}
    2017-11-22 11:55:17.449 INFO 14721 --- [ main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.MySQL5Dialect
    2017-11-22 11:55:17.665 INFO 14721 --- [ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'

    Article.kt

    package com.kotlin.springboot.nextj2ee.entity
    
    import java.util.*
    import javax.persistence.*
    
    @Entity
    class Article {
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        var id: Long = -1
    
        lateinit var author: String
        lateinit var title: String
        @Column(name = "url", unique = true, length = 512)
        lateinit var url: String
        @Lob
        lateinit var content: String
        lateinit var gmtCreate: Date
        lateinit var gmtModify: Date
    
    }
    
    

    对应的Hibernate 启动日志

    Hibernate: 
        
        drop table if exists article
    Hibernate: 
        
        create table article (
           id bigint not null auto_increment,
            author varchar(255),
            content longtext,
            gmt_create datetime,
            gmt_modify datetime,
            title varchar(255),
            url varchar(250),
            primary key (id)
        ) engine=MyISAM
    Hibernate: 
        
        alter table article 
           add constraint UK_la4e9l2g2otn85r9ih4btnmi unique (url)
    

    url varchar(250)

    Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Specified key was too long; max key length is 1000 bytes
        at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:na]
        at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:na]
        at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:na]
        at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:488) ~[na:na]
        at com.mysql.jdbc.Util.handleNewInstance(Util.java:425) ~[mysql-connector-java-5.1.44.jar:5.1.44]
        at com.mysql.jdbc.Util.getInstance(Util.java:408) ~[mysql-connector-java-5.1.44.jar:5.1.44]
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:943) ~[mysql-connector-java-5.1.44.jar:5.1.44]
        at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3973) ~[mysql-connector-java-5.1.44.jar:5.1.44]
        at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3909) ~[mysql-connector-java-5.1.44.jar:5.1.44]
        at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2527) ~[mysql-connector-java-5.1.44.jar:5.1.44]
        at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2680) ~[mysql-connector-java-5.1.44.jar:5.1.44]
        at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2483) ~[mysql-connector-java-5.1.44.jar:5.1.44]
        at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2441) ~[mysql-connector-java-5.1.44.jar:5.1.44]
        at com.mysql.jdbc.StatementImpl.executeInternal(StatementImpl.java:845) ~[mysql-connector-java-5.1.44.jar:5.1.44]
        at com.mysql.jdbc.StatementImpl.execute(StatementImpl.java:745) ~[mysql-connector-java-5.1.44.jar:5.1.44]
        at com.zaxxer.hikari.pool.ProxyStatement.execute(ProxyStatement.java:95) ~[HikariCP-2.7.2.jar:na]
        at com.zaxxer.hikari.pool.HikariProxyStatement.execute(HikariProxyStatement.java) ~[HikariCP-2.7.2.jar:na]
        at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept(GenerationTargetToDatabase.java:54) ~[hibernate-core-5.2.12.Final.jar:5.2.12.Final]
        ... 33 common frames omitted
    
    

    由 Entity 类生成的表结构:

    image.png

    唯一索引信息:

    image.png

    MySQL 的 utf8mb4 (most bytes 4)编码

    一、简介

    MySQL在5.5.3之后增加了这个utf8mb4的编码,mb4就是most bytes 4的意思,专门用来兼容四字节的unicode。好在utf8mb4是utf8的超集,除了将编码改为utf8mb4外不需要做其他转换。当然,为了节省空间,一般情况下使用utf8也就够了。

    二、内容描述

    那上面说了既然utf8能够存下大部分中文汉字,那为什么还要使用utf8mb4呢? 原来mysql支持的 utf8 编码最大字符长度为 3 字节,如果遇到 4 字节的宽字符就会插入异常了。三个字节的 UTF-8 最大能编码的 Unicode 字符是 0xffff,也就是 Unicode 中的基本多文种平面(BMP)。也就是说,任何不在基本多文本平面的 Unicode字符,都无法使用 Mysql 的 utf8 字符集存储。包括 Emoji 表情(Emoji 是一种特殊的 Unicode 编码,常见于 ios 和 android 手机上),和很多不常用的汉字,以及任何新增的 Unicode 字符等等。
    三、问题根源
    最初的 UTF-8 格式使用一至六个字节,最大能编码 31 位字符。最新的 UTF-8 规范只使用一到四个字节,最大能编码21位,正好能够表示所有的 17个 Unicode 平面。
    utf8 是 Mysql 中的一种字符集,只支持最长三个字节的 UTF-8字符,也就是 Unicode 中的基本多文本平面。
    Mysql 中的 utf8 为什么只支持持最长三个字节的 UTF-8字符呢?我想了一下,可能是因为 Mysql 刚开始开发那会,Unicode 还没有辅助平面这一说呢。那时候,Unicode 委员会还做着 “65535 个字符足够全世界用了”的美梦。Mysql 中的字符串长度算的是字符数而非字节数,对于 CHAR 数据类型来说,需要为字符串保留足够的长。当使用 utf8 字符集时,需要保留的长度就是 utf8 最长字符长度乘以字符串长度,所以这里理所当然的限制了 utf8 最大长度为 3,比如 CHAR(100) Mysql 会保留 300字节长度。至于后续的版本为什么不对 4 字节长度的 UTF-8 字符提供支持,我想一个是为了向后兼容性的考虑,还有就是基本多文种平面之外的字符确实很少用到。
    要在 Mysql 中保存 4 字节长度的 UTF-8 字符,需要使用 utf8mb4 字符集,但只有 5.5.3 版本以后的才支持(查看版本: select version();)。我觉得,为了获取更好的兼容性,应该总是使用 utf8mb4 而非 utf8. 对于 CHAR 类型数据,utf8mb4 会多消耗一些空间,根据 Mysql 官方建议,使用 VARCHAR 替代 CHAR。

    16.4 本章小结

    相关文章

      网友评论

        本文标题:第16章 Spring Boot + Kotlin: 下一代 J

        本文链接:https://www.haomeiwen.com/subject/xalnvxtx.html