JTDS 尝试(但失败了)在应用程序启动时重新创建已经存在的 table

JTDS tries (and fails) to recreate already-existing table on application start

我正在尝试编写一个应用程序来连接到 MS SQL 服务器数据库。数据库已存在,table 已配置。我想要做的就是将我的 Java Spring 应用程序连接到已经存在的服务器。但是,当我尝试这样做时,出现此错误:

Caused by: java.sql.SQLException: There is already an object named 'Customer' in the database.
at net.sourceforge.jtds.jdbc.SQLDiagnostic.addDiagnostic(SQLDiagnostic.java:372) ~[jtds-1.3.1.jar:1.3.1]
at net.sourceforge.jtds.jdbc.TdsCore.tdsErrorToken(TdsCore.java:2988) ~[jtds-1.3.1.jar:1.3.1]
at net.sourceforge.jtds.jdbc.TdsCore.nextToken(TdsCore.java:2421) ~[jtds-1.3.1.jar:1.3.1]
at net.sourceforge.jtds.jdbc.TdsCore.getMoreResults(TdsCore.java:671) ~[jtds-1.3.1.jar:1.3.1]
at net.sourceforge.jtds.jdbc.JtdsStatement.processResults(JtdsStatement.java:613) ~[jtds-1.3.1.jar:1.3.1]
at net.sourceforge.jtds.jdbc.JtdsStatement.executeSQL(JtdsStatement.java:572) ~[jtds-1.3.1.jar:1.3.1]
at net.sourceforge.jtds.jdbc.JtdsStatement.executeImpl(JtdsStatement.java:809) ~[jtds-1.3.1.jar:1.3.1]
at net.sourceforge.jtds.jdbc.JtdsStatement.execute(JtdsStatement.java:1282) ~[jtds-1.3.1.jar:1.3.1]
at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept(GenerationTargetToDatabase.java:54) ~[hibernate-core-5.1.10.Final.jar:5.1.10.Final]
... 87 common frames omitted

似乎 JTDS 正在尝试重新创建我的客户 table,实际上如果我删除 table 然后 运行 应用程序,它确实会创建一个新的 table 在我的数据库中称为 "Customer"。但是,我不能在每次应用程序启动时删除我的 table(出于显而易见的原因),因此我需要配置我的应用程序以连接到已经存在的 table。我该怎么做?

数据库应用程序配置:

@Configuration
@EnableJpaRepositories
@EntityScan("com.example.dbentity")
public class AppConfig {

@Value("${db.driver.class.name}")
private String dbDriverClassName;

@Value("${db.prefix}")
private String dbPrefix;

@Value("${db.url}")
private String dbUrl;

@Value("${db.name}")
private String dbName;

@Value("${db.username}")
private String dbUsername;

@Value("${db.password}")
private String dbPassword;

@Bean
public DataSource DataSource() {
    DriverManagerDataSource dataSource = new DriverManagerDataSource();
    dataSource.setDriverClassName(dbDriverClassName);
    String connectionUrl = dbPrefix + dbUrl + "/" +dbName;
    dataSource.setUrl(connectionUrl);
    dataSource.setUsername(dbUsername);
    dataSource.setPassword(dbPassword);

    return dataSource;
}

@Bean
public JdbcTemplate JdbcTemplate() {
    JdbcTemplate template = new JdbcTemplate();
    template.setDataSource(DataSource());
    return template;
}

@Bean
public EntityManagerFactory entityManagerFactory() {
    HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
    vendorAdapter.setGenerateDdl(true);
    LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
    factory.setJpaVendorAdapter(vendorAdapter);
    factory.setPackagesToScan("com.example.dbentity");
    factory.setDataSource(DataSource());
    factory.afterPropertiesSet();
    return factory.getObject();
}

@Bean
public PlatformTransactionManager transactionManager() {
    JpaTransactionManager txManager = new JpaTransactionManager();
    txManager.setEntityManagerFactory(entityManagerFactory());
    return txManager;
}
}

配置 YAML:

spring:
  application:
    name: sample-application
  jpa:
    hibernate:
      ddl-auto: validate

server:
  port: 8080
  max-http-header-size: 65536

db:
  driver:
    class:
      name: net.sourceforge.jtds.jdbc.Driver
  prefix: jdbc:jtds:sqlserver://
  url: example-server.net:1433
  name: example-db
  username: user
  password: password

休眠输出:

2018-07-13 10:57:56.831  INFO 15336 --- [           main] o.s.j.d.DriverManagerDataSource          : Loaded JDBC driver: net.sourceforge.jtds.jdbc.Driver
2018-07-13 10:57:56.882  INFO 15336 --- [           main] j.LocalContainerEntityManagerFactoryBean : Building JPA container EntityManagerFactory for persistence unit 'default'
2018-07-13 10:57:56.901  INFO 15336 --- [           main] o.hibernate.jpa.internal.util.LogHelper  : HHH000204: Processing PersistenceUnitInfo [
name: default
...]
2018-07-13 10:57:57.002  INFO 15336 --- [           main] org.hibernate.Version                    : HHH000412: Hibernate Core {5.1.10.Final}
2018-07-13 10:57:57.002  INFO 15336 --- [           main] org.hibernate.cfg.Environment            : HHH000206: hibernate.properties not found
2018-07-13 10:57:57.006  INFO 15336 --- [           main] org.hibernate.cfg.Environment            : HHH000021: Bytecode provider name : javassist
2018-07-13 10:57:57.060  INFO 15336 --- [           main] o.hibernate.annotations.common.Version   : HCANN000001: Hibernate Commons Annotations {5.0.1.Final}
2018-07-13 10:57:57.531  INFO 15336 --- [           main] org.hibernate.dialect.Dialect            : HHH000400: Using dialect: org.hibernate.dialect.SQLServer2012Dialect
2018-07-13 10:57:57.672  INFO 15336 --- [           main] o.h.e.j.e.i.LobCreatorBuilderImpl        : HHH000423: Disabling contextual LOB creation as JDBC driver reported JDBC version [3] less than 4
2018-07-13 10:57:58.754  WARN 15336 --- [           main] o.h.t.s.i.ExceptionHandlerLoggedImpl     : GenerationTarget encountered exception accepting command : Error executing DDL via JDBC Statement

谢谢。

Hibernate 有一个名为 ddl-auto 的 属性,您可以在其中设置 Hibernate 是否 create 启动时的架构,validate 已经存在的架构,或者不验证现有架构。

你想做的就是使用validate(或none)。

请参阅 here for how to configure this in Spring Boot and here(即 hibernateProperties)了解如何在 Vanilla Spring 中执行此操作。