Spring 引导的两个或多个 (Oracle) 数据库上的多个存储过程?
Multiple stored procedures on two or more (Oracle) databases with Spring Boot?
我正在设置一个 Java Spring 项目,其中包含两个完全不同的 Oracle 数据库的多个 StoredProcedures。
不允许使用任何自动生成的 SQL。
我没有在任何地方找到完整的解决方案或实施示例,因此我将尝试在这里总结问题和干净的解决方案。
我真诚地希望有一天这会对某人有所帮助。
您将需要一个有效的 Spring 引导项目。
请让我知道是否有任何混淆,我应该更好地解释它。
数据库连接设置
数据库连接属性(db.properties)
请将此文件放在资源文件夹中。
db1.datasource.url=jdbc:oracle:thin:@url:sid
db1.datasource.username=username
db1.datasource.password=password
db1.datasource.driver-class-name=oracle.jdbc.OracleDriver
db2.datasource.url=jdbc:oracle:thin:@url:sid
db2.datasource.username=username
db2.datasource.password=password
db2.datasource.driver-class-name=oracle.jdbc.OracleDriver
数据库配置class (DbConfiguration.java)
@Configuration
@Order(1)
@PropertySource("classpath:/db.properties")
public class DbConfiguration {
/**
* Configuration beans for establishing a connection to db1 database.
* The primary database dataSource is automatically populated to the constructor in StoredProcedure extended class.
*/
@Bean
@Primary
@ConfigurationProperties("db1.datasource")
public DataSourceProperties db1DataSourceProperties() {
return new DataSourceProperties();
}
@Bean(name = "db1")
@Primary
public DataSource db1DataSource() {
return db1DataSourceProperties().initializeDataSourceBuilder().build();
}
/**
* Configuration beans for establishing a connection to db2 database.
*/
@Bean
@ConfigurationProperties("db2.datasource")
public DataSourceProperties db2DataSourceProperties() {
return new DataSourceProperties();
}
@Bean(name = "db2")
public DataSource db2DataSource() {
return db2DataSourceProperties().initializeDataSourceBuilder().build();
}
Db1 存储过程classes
用于检索单笔付款的存储过程 (SPGetSinglePayment.java)
/**
* The type Sp get payment.
* A StoredProcedure class where we define IN and OUT parameters.
*/
@Component
public class SPGetSinglePayment extends StoredProcedure {
public static final String PROCEDURE_GET_PAYMENT = "GET_PAYMENT";
public static final String PROCEDURE_GET_PAYMENT_PARAM_IN_ID = "P_PAYMENT_ID";
public static final String PROCEDURE_GET_PAYMENT_PARAM_OUT_RESULT = "PAYMENT_RESULT";
public SPGetSinglePayment(final DataSource dataSource) {
super(dataSource, PACKAGE_NAME + PROCEDURE_GET_PAYMENT);
declareParameter(new SqlParameter(PROCEDURE_GET_PAYMENT_PARAM_IN_ID, OracleTypes.VARCHAR));
declareParameter(new SqlOutParameter(PROCEDURE_GET_PAYMENT_PARAM_OUT_RESULT, OracleTypes.CURSOR));
compile();
}
}
StoredProcedure 响应生成器 class (SinglePaymentResponseBuilder.java)
/**
* The type Payment response builder. Gets an object from Oracle DB and populates POJOs.
*/
@Component
public class SinglePaymentResponseBuilder {
/**
* Builds list of payment transaction details from stored procedure result set.
*
* @param getPaymentObject the object containing payment details result set
* @param getItineraryDataObject the object containing itinerary data result set
* @return list of payment details for payment
*/
public List<SinglePaymentDto> build(final Object getPaymentObject, final Object getItineraryDataObject) {
final List<Map<String, Object>> spMap = getListOfObjectMaps(getPaymentObject);
final List<SinglePaymentDto> response = new ArrayList<>();
for (Map<String, Object> dtos : spMap) {
SinglePaymentDto payment = new SinglePaymentDto(
new PaymentInfo(getStringValue(dtos.get(PaymentInfo.PAYMENT_ID)),
... build and return response
StoredProcedure 助手 class (StoredProcedureHelper.java)
这里我们实际上对一个数据库执行了两个存储过程。
/**
* Contains methods to call Oracle prepared statements. Responsible for handling procedure specific input and output parameters.
*/
@Component
public class StoredProcedureHelper {
public static final String PACKAGE_NAME = "A_PACKAGE_NAME.";
private final SPGetSinglePayment getSinglePayment;
private final SinglePaymentResponseBuilder singlePaymentResponseBuilder;
@Autowired
public StoredProcedureHelper(
final SPGetSinglePayment getSinglePayment,
final SinglePaymentResponseBuilder singlePaymentResponseBuilder,
...){
this.getSinglePayment = getSinglePayment;
this.singlePaymentResponseBuilder = singlePaymentResponseBuilder;
...
}
/**
* Calls stored procedure to get all payment details for given payment.
*
* @param id the payment id
* @return payment details
*/
public List<SinglePaymentDto> findSinglePayment(final String id) {
LOG.info(LOG_PATTERN, SPGetSinglePayment.class.getSimpleName(),
PACKAGE_NAME, PROCEDURE_GET_PAYMENT);
Object spGetPaymentResult = getSinglePayment.execute(id).get(PROCEDURE_GET_PAYMENT_PARAM_OUT_RESULT);
Object spGetItineraryDataResult = getItineraryData.execute(id).get(PROCEDURE_GET_ITINERARY_DATA_PARAM_OUT_RESULT);
return singlePaymentResponseBuilder.build(spGetPaymentResult, spGetItineraryDataResult);
}
Db2 存储过程classes
用于从其标识符令牌 (SPGetToothbrush.java) 中检索解密牙刷的存储过程
我想在这里 class 下面公开。请注意,如果您想使用 db2,则必须通过 @Qualifier 注释来定义它。
对于每个存储过程,其他 classes 将遵循上述模式。
根据要求,我还可以提供单元测试示例。
/**
* The type Sp get toothbrush.
* A StoredProcedure class where we define IN and OUT parameters.
*/
@Component
public class SPGetToothbrush extends StoredProcedure {
public static final String PROCEDURE_GET_TOOTHBRUSH = "GET_IDENTIFIER";
public static final String PROCEDURE_GET_TOOTHBRUSH_PARAM_IN_INSTRUMENT_ID = "P_TOKEN";
public static final String PROCEDURE_GET_TOOTHBRUSH_PARAM_OUT_RESULT = "OUT_IDENTIFIER";
/**
* Instantiates a new Sp get toothbrush.
*
* @param dataSource is populated by db2 properties by use of @Qualifier.
*/
public SPGetToothbrush(@Qualifier("db2") final DataSource dataSource) {
super(dataSource, StoredProcedureToothbrushHelper.PACKAGE_NAME + PROCEDURE_GET_TOOTHBRUSH);
declareParameter(new SqlParameter(PROCEDURE_GET_TOOTHBRUSH_PARAM_IN_INSTRUMENT_ID, OracleTypes.VARCHAR));
declareParameter(new SqlOutParameter(PROCEDURE_GET_TOOTHBRUSH_PARAM_OUT_RESULT, OracleTypes.VARCHAR));
compile();
}
}
我正在设置一个 Java Spring 项目,其中包含两个完全不同的 Oracle 数据库的多个 StoredProcedures。 不允许使用任何自动生成的 SQL。 我没有在任何地方找到完整的解决方案或实施示例,因此我将尝试在这里总结问题和干净的解决方案。 我真诚地希望有一天这会对某人有所帮助。
您将需要一个有效的 Spring 引导项目。
请让我知道是否有任何混淆,我应该更好地解释它。
数据库连接设置
数据库连接属性(db.properties)
请将此文件放在资源文件夹中。
db1.datasource.url=jdbc:oracle:thin:@url:sid
db1.datasource.username=username
db1.datasource.password=password
db1.datasource.driver-class-name=oracle.jdbc.OracleDriver
db2.datasource.url=jdbc:oracle:thin:@url:sid
db2.datasource.username=username
db2.datasource.password=password
db2.datasource.driver-class-name=oracle.jdbc.OracleDriver
数据库配置class (DbConfiguration.java)
@Configuration
@Order(1)
@PropertySource("classpath:/db.properties")
public class DbConfiguration {
/**
* Configuration beans for establishing a connection to db1 database.
* The primary database dataSource is automatically populated to the constructor in StoredProcedure extended class.
*/
@Bean
@Primary
@ConfigurationProperties("db1.datasource")
public DataSourceProperties db1DataSourceProperties() {
return new DataSourceProperties();
}
@Bean(name = "db1")
@Primary
public DataSource db1DataSource() {
return db1DataSourceProperties().initializeDataSourceBuilder().build();
}
/**
* Configuration beans for establishing a connection to db2 database.
*/
@Bean
@ConfigurationProperties("db2.datasource")
public DataSourceProperties db2DataSourceProperties() {
return new DataSourceProperties();
}
@Bean(name = "db2")
public DataSource db2DataSource() {
return db2DataSourceProperties().initializeDataSourceBuilder().build();
}
Db1 存储过程classes
用于检索单笔付款的存储过程 (SPGetSinglePayment.java)
/**
* The type Sp get payment.
* A StoredProcedure class where we define IN and OUT parameters.
*/
@Component
public class SPGetSinglePayment extends StoredProcedure {
public static final String PROCEDURE_GET_PAYMENT = "GET_PAYMENT";
public static final String PROCEDURE_GET_PAYMENT_PARAM_IN_ID = "P_PAYMENT_ID";
public static final String PROCEDURE_GET_PAYMENT_PARAM_OUT_RESULT = "PAYMENT_RESULT";
public SPGetSinglePayment(final DataSource dataSource) {
super(dataSource, PACKAGE_NAME + PROCEDURE_GET_PAYMENT);
declareParameter(new SqlParameter(PROCEDURE_GET_PAYMENT_PARAM_IN_ID, OracleTypes.VARCHAR));
declareParameter(new SqlOutParameter(PROCEDURE_GET_PAYMENT_PARAM_OUT_RESULT, OracleTypes.CURSOR));
compile();
}
}
StoredProcedure 响应生成器 class (SinglePaymentResponseBuilder.java)
/**
* The type Payment response builder. Gets an object from Oracle DB and populates POJOs.
*/
@Component
public class SinglePaymentResponseBuilder {
/**
* Builds list of payment transaction details from stored procedure result set.
*
* @param getPaymentObject the object containing payment details result set
* @param getItineraryDataObject the object containing itinerary data result set
* @return list of payment details for payment
*/
public List<SinglePaymentDto> build(final Object getPaymentObject, final Object getItineraryDataObject) {
final List<Map<String, Object>> spMap = getListOfObjectMaps(getPaymentObject);
final List<SinglePaymentDto> response = new ArrayList<>();
for (Map<String, Object> dtos : spMap) {
SinglePaymentDto payment = new SinglePaymentDto(
new PaymentInfo(getStringValue(dtos.get(PaymentInfo.PAYMENT_ID)),
... build and return response
StoredProcedure 助手 class (StoredProcedureHelper.java)
这里我们实际上对一个数据库执行了两个存储过程。
/**
* Contains methods to call Oracle prepared statements. Responsible for handling procedure specific input and output parameters.
*/
@Component
public class StoredProcedureHelper {
public static final String PACKAGE_NAME = "A_PACKAGE_NAME.";
private final SPGetSinglePayment getSinglePayment;
private final SinglePaymentResponseBuilder singlePaymentResponseBuilder;
@Autowired
public StoredProcedureHelper(
final SPGetSinglePayment getSinglePayment,
final SinglePaymentResponseBuilder singlePaymentResponseBuilder,
...){
this.getSinglePayment = getSinglePayment;
this.singlePaymentResponseBuilder = singlePaymentResponseBuilder;
...
}
/**
* Calls stored procedure to get all payment details for given payment.
*
* @param id the payment id
* @return payment details
*/
public List<SinglePaymentDto> findSinglePayment(final String id) {
LOG.info(LOG_PATTERN, SPGetSinglePayment.class.getSimpleName(),
PACKAGE_NAME, PROCEDURE_GET_PAYMENT);
Object spGetPaymentResult = getSinglePayment.execute(id).get(PROCEDURE_GET_PAYMENT_PARAM_OUT_RESULT);
Object spGetItineraryDataResult = getItineraryData.execute(id).get(PROCEDURE_GET_ITINERARY_DATA_PARAM_OUT_RESULT);
return singlePaymentResponseBuilder.build(spGetPaymentResult, spGetItineraryDataResult);
}
Db2 存储过程classes
用于从其标识符令牌 (SPGetToothbrush.java) 中检索解密牙刷的存储过程
我想在这里 class 下面公开。请注意,如果您想使用 db2,则必须通过 @Qualifier 注释来定义它。 对于每个存储过程,其他 classes 将遵循上述模式。 根据要求,我还可以提供单元测试示例。
/**
* The type Sp get toothbrush.
* A StoredProcedure class where we define IN and OUT parameters.
*/
@Component
public class SPGetToothbrush extends StoredProcedure {
public static final String PROCEDURE_GET_TOOTHBRUSH = "GET_IDENTIFIER";
public static final String PROCEDURE_GET_TOOTHBRUSH_PARAM_IN_INSTRUMENT_ID = "P_TOKEN";
public static final String PROCEDURE_GET_TOOTHBRUSH_PARAM_OUT_RESULT = "OUT_IDENTIFIER";
/**
* Instantiates a new Sp get toothbrush.
*
* @param dataSource is populated by db2 properties by use of @Qualifier.
*/
public SPGetToothbrush(@Qualifier("db2") final DataSource dataSource) {
super(dataSource, StoredProcedureToothbrushHelper.PACKAGE_NAME + PROCEDURE_GET_TOOTHBRUSH);
declareParameter(new SqlParameter(PROCEDURE_GET_TOOTHBRUSH_PARAM_IN_INSTRUMENT_ID, OracleTypes.VARCHAR));
declareParameter(new SqlOutParameter(PROCEDURE_GET_TOOTHBRUSH_PARAM_OUT_RESULT, OracleTypes.VARCHAR));
compile();
}
}