通过TNS与Oracle的连接不工作
我有一个Spring Boot应用程序,当它以经典的方式连接到Oracle实例时,它可以顺利工作:通过TNS与Oracle的连接不工作,oracle,spring-boot,tnsnames,tns,Oracle,Spring Boot,Tnsnames,Tns,我有一个Spring Boot应用程序,当它以经典的方式连接到Oracle实例时,它可以顺利工作: jdbc:oracle:thin:@<server name>:<port num>/<service name> 以下是我的application.properties+application-oracleprod.properties文件。请记住,如前所述,当我使用SID连接时,这种方法是有效的 application.properties: spring
jdbc:oracle:thin:@<server name>:<port num>/<service name>
以下是我的application.properties+application-oracleprod.properties文件。请记住,如前所述,当我使用SID连接时,这种方法是有效的
application.properties:
spring.profiles.active=oracleprod
spring.jpa.database-platform=org.hibernate.dialect.Oracle10gDialect
spring.jpa.hibernate.ddl-auto=validate
hibernate.show_sql=true
hibernate.hbm2ddl.auto=update
hibernate.generate_statistics=true
application-oracleprod.properties(此处的神奇之处在于该属性“oracle.net.tns_admin”设置了“tnsnames.ora”文件夹和链接“@MY_SERVICE”,该链接显然存在于“tnsnames.ora”文件中,但我真的看不到oracle在幕后做什么):
配置类简洁明了:
@Configuration
@ConfigurationProperties(prefix="oracle" )
public class OracleConfiguration {
@NotNull
private String username;
@NotNull
private String password;
@NotNull
private String url;
/*@Value("${oracle.net.tns_admin}")
private String tns;*/
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
public void setUrl(String url) {
this.url = url;
}
/*public void setTns(String tns) {
this.tns = tns;
}*/
@Bean
DataSource dataSource() throws SQLException {
OracleDataSource dataSource = new OracleDataSource(); // we use oracle data source API but it could be mysql
dataSource.setURL(this.url);
dataSource.setUser(this.username);
dataSource.setPassword(this.password);
dataSource.setImplicitCachingEnabled(true);
dataSource.setFastConnectionFailoverEnabled(true);
return dataSource;
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
try {
em.setDataSource(dataSource());
} catch (SQLException e) {
e.printStackTrace();
}
em.setPackagesToScan(new String[] { "app.persistence.entity" }); // put the name of entity classes package
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
//em.setJpaProperties(additionalProperties()); // this properties are set by "application-oracle.properties" file
return em;
}
@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(emf);
return transactionManager;
}
总而言之,我遵循了Oracle文档中建议的方法,结合Spring引导配置文件/类,但运气不佳
我还尝试了不同的路径格式:
C:/ORACLE/Client11g/network/admin/tnsnames.ora
C:\ORACLE\Client11g\network\admin
C:\\ORACLE\\Client11g\\network\\admin
我认为我做得很好,因为有了SID连接,一切都很完美,但可能缺少了隐藏的东西
更新
事实证明,db url不正确,至少对于TNS连接是这样。问题是我们有多台主机,而不仅仅是一台:
MY_SERVICE =
(DESCRIPTION_LIST =
(LOAD_BALANCE = off)
(FAILOVER = on)
(DESCRIPTION =
(CONNECT_TIMEOUT = 5)
(TRANSPORT_CONNECT_TIMEOUT = 3)
(RETRY_COUNT = 3)
(ADDRESS_LIST =
(LOAD_BALANCE = on)
(ADDRESS = (PROTOCOL = TCP)(HOST = <ip_1> )(PORT = 1621))
(ADDRESS = (PROTOCOL = TCP)(HOST = <ip_2> )(PORT = 1621))
)
(CONNECT_DATA =
(SERVICE_NAME = <my_service_name>)
)
)
(DESCRIPTION =
(CONNECT_TIMEOUT = 5)
(TRANSPORT_CONNECT_TIMEOUT = 3)
(RETRY_COUNT = 3)
(ADDRESS_LIST =
(LOAD_BALANCE = on)
(ADDRESS = (PROTOCOL = TCP)(HOST = <ip_3> )(PORT = 1621))
(ADDRESS = (PROTOCOL = TCP)(HOST = <ip_4> )(PORT = 1621))
)
(CONNECT_DATA =
(SERVICE_NAME = <my_service_name> )
)
)
)
再一次,我有点困惑如何告诉Spring如何阅读这个TNS配置
有什么想法吗?在您的类中,您基本上禁用了自动配置,从而使大部分
应用程序的属性变得无用
您的OracleConfiguration
中没有任何内容不是(或可以)为您自动配置的
注意:我假设有两件事,第一件是用作连接池,第二件是使用Spring Boot 1.4.x
因此,对于初学者来说,删除OracleConfiguration
类并相应地修复应用程序.properties
# DataSource
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
#JPA
spring.jpa.hibernate.ddl-auto=validate
#Hibernate
spring.jpa.properties.hibernate.show_sql=true
spring.jpa.properties.hibernate.generate_statistics=true
您不需要spring.datasource.driver类名,因为它将从URL派生
在您的应用程序oracle.properties
(或您使用的任何配置文件名称)中,设置以下内容
# DataSource
spring.datasource.username=my_user
spring.datasource.password=xyz
spring.datasource.url=jdbc:oracle:thin:@MY_SERVICE
spring.datasource.hikari.dataSourceClassName=oracle.jdbc.pool.OracleDataSource
spring.datasource.hikari.dataSourceProperties.implicitCachingEnabled=true
spring.datasource.hikari.dataSourceProperties.fastConnectionFailoverEnabled=true
#JPA
spring.jpa.database-platform=org.hibernate.dialect.Oracle10gDialect
这将配置oracle特定的JDBC属性
需要spring.datasource.hikari.datasourceproperty
来设置OracleDataSource
中的附加属性
这应该允许Spring Boot自动创建数据源
和相应的EntityManager工厂
,而无需创建自定义配置类
更新(配置不带Hikari和普通的OracleDataSource
)
如果要使用普通的OracleDataSource
而不是连接池,可以从默认的应用程序.properties
中删除spring.datasource.type
,并将以下内容添加到应用程序oracle.properties
# DataSource
spring.datasource.type=oracle.jdbc.pool.OracleDataSource
spring.datasource.username=my_user
spring.datasource.password=xyz
spring.datasource.url=jdbc:oracle:thin:@MY_SERVICE
其结果或多或少与您手动配置的结果相同
更新#2
要使用TNS,还需要设置名为oracle.net.TNS\u admin的系统属性。(见附件)
因此,在应用程序初始值设定项中(如果未在应用程序服务器上设置),您需要手动设置它
private static void determineAndSetTnsHome() {
String tnsAdmin = System.getenv("TNS_ADMIN");
if (tnsAdmin == null) {
String oracleHome = System.getenv("ORACLE_HOME");
if (oracleHome == null) {
return; //failed to find any useful env variables
}
tnsAdmin = oracleHome + File.separatorChar + "network" + File.separatorChar + "admin";
}
System.setProperty("oracle.net.tns_admin", tnsAdmin);
}
从main
和onstart
或configure
方法调用此方法。这假设您的环境中设置了ORACLE\u HOME
或TNS\u ADMIN
变量。出于某种原因,仅对我有效:
spring.datasource.url=jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=tcp)(HOST=TODO)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=TODO)))
而不是spring.datasource.url=jdbc:oracle:thin:@myu服务。
另外,我正在调用用户m.Deinum在接受的答案中建议的determineAndSettnHome()方法:
public static void main(String[] args) {
SpringApplication.run(EvaApplication.class, args);
determineAndSetTnsHome();
}
实际上是跛脚的方法,,
但它工作得很好
把这个放在你的主课上
System.setProperty("oracle.net.tns_admin",
"<Path of tnsnames.ora>");
System.setProperty(“oracle.net.tns_admin”,
"");
在属性文件中使用此选项
spring.datasource.url=jdbc:oracle:thin:@ORCLPDB
我还在挖。将在此处更新您在此处输入了大量代码,任何人都很难先理解您的问题,然后再回答。提问时请具体、准确。在发布问题之前,请先看一看。您正在将spring.jpa.database-platform设置为Oracle方言,是否也尝试过设置hibernate属性?(按照异常中的要求)因此,您正在应用程序中设置属性。属性用于自动配置。接下来创建您自己的配置,禁用自动配置,并发现没有应用这些属性很奇怪。简而言之,应用程序中没有属性。将使用/应用属性。问题出现了,为什么你有这个配置类?您并不真正需要它,因为Spring Boot可以为您即时配置所有这些。@GeekyNinja省略这些代码不会显示完整且可验证的代码example@Turo我不明白你指的是哪一处房产。你能解释清楚吗?谢谢。它实际上与SID连接一起工作。但是,我仍然面临TNS连接的问题。此时,我想知道配置类的用途。是否需要在不依赖.properties文件的情况下手动配置数据源(在代码中指定连接条件)?您不需要配置类。(你在评论中提出的问题是另一个问题)。我非常怀疑,对于这个配置文件,您是否会得到相同的异常(如果您删除了配置类)。我已经更新了主要问题。TNS连接的问题仍然存在,但我当然误解了数据源配置。你救了我一天。我想知道为什么在.properties文件中添加属性“oracle.net.tns_admin”不会起作用。这肯定会更干净、更高效。我将进一步研究一种不在spring引导“Application.java”中添加额外代码的方法。原因是我会离开李
spring.datasource.url=jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=tcp)(HOST=TODO)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=TODO)))
public static void main(String[] args) {
SpringApplication.run(EvaApplication.class, args);
determineAndSetTnsHome();
}
System.setProperty("oracle.net.tns_admin",
"<Path of tnsnames.ora>");