← Назад к вопросам
Как записывать данные из нескольких источников в Oracle
2.0 Middle🔥 161 комментариев
#ORM и Hibernate#Базы данных и SQL
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Ответ
Запись данных из нескольких источников в Oracle требует правильной обработки синхронизации, транзакций и обработки ошибок. Рассмотрю несколько подходов.
1. Использование пула потоков с синхронизацией
public class MultiSourceOracleWriter {
private final OracleConnectionPool connectionPool;
private final ExecutorService executorService;
private final List<DataSource> sources;
public void writeFromMultipleSources() {
List<Future<?>> futures = new ArrayList<>();
for (DataSource source : sources) {
futures.add(executorService.submit(() -> {
try (Connection conn = connectionPool.getConnection()) {
List<Record> records = source.fetchData();
insertRecords(conn, records);
} catch (SQLException e) {
handleError(e);
}
}));
}
// Ожидаем завершения всех потоков
for (Future<?> future : futures) {
future.get();
}
}
private void insertRecords(Connection conn, List<Record> records)
throws SQLException {
conn.setAutoCommit(false);
try {
for (Record record : records) {
insertRecord(conn, record);
}
conn.commit();
} catch (SQLException e) {
conn.rollback();
throw e;
}
}
}
2. Batch Insert для производительности
public void batchInsertRecords(Connection conn, List<Record> records)
throws SQLException {
String sql = "INSERT INTO table_name (id, name, value) VALUES (?, ?, ?)";
try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
conn.setAutoCommit(false);
for (int i = 0; i < records.size(); i++) {
Record record = records.get(i);
pstmt.setInt(1, record.getId());
pstmt.setString(2, record.getName());
pstmt.setBigDecimal(3, record.getValue());
pstmt.addBatch();
// Выполняем батч каждые 1000 записей
if ((i + 1) % 1000 == 0) {
pstmt.executeBatch();
conn.commit();
}
}
// Выполняем оставшиеся записи
pstmt.executeBatch();
conn.commit();
} catch (SQLException e) {
conn.rollback();
throw e;
}
}
3. Использование ORM (Hibernate)
@Service
public class MultiSourceHibernateWriter {
@Autowired
private SessionFactory sessionFactory;
@Transactional
public void writeFromMultipleSources(List<DataSource> sources) {
Session session = sessionFactory.openSession();
Transaction txn = session.beginTransaction();
try {
int batchSize = 1000;
int count = 0;
for (DataSource source : sources) {
List<Entity> entities = source.fetchEntities();
for (Entity entity : entities) {
session.save(entity);
if (++count % batchSize == 0) {
session.flush();
session.clear();
}
}
}
txn.commit();
} catch (Exception e) {
txn.rollback();
throw e;
} finally {
session.close();
}
}
}
4. Обработка конфликтов и дедупликации
public void writeWithDeduplication(Connection conn, List<Record> records)
throws SQLException {
String mergeSql = "MERGE INTO table_name t USING dual d " +
"ON (t.id = ?) " +
"WHEN MATCHED THEN UPDATE SET t.value = ? " +
"WHEN NOT MATCHED THEN INSERT (id, value) VALUES (?, ?)";
try (PreparedStatement pstmt = conn.prepareStatement(mergeSql)) {
conn.setAutoCommit(false);
for (Record record : records) {
pstmt.setInt(1, record.getId());
pstmt.setBigDecimal(2, record.getValue());
pstmt.setInt(3, record.getId());
pstmt.setBigDecimal(4, record.getValue());
pstmt.addBatch();
}
pstmt.executeBatch();
conn.commit();
} catch (SQLException e) {
conn.rollback();
throw e;
}
}
5. Использование Spring Data с многоисточниковостью
@Configuration
public class DataSourceConfig {
@Bean
public DataSource primaryDataSource() { ... }
@Bean
public DataSource secondaryDataSource() { ... }
}
@Service
public class MultiSourceService {
@Autowired
@Qualifier("primaryDataSource")
private DataSource primary;
@Autowired
@Qualifier("secondaryDataSource")
private DataSource secondary;
public void syncData() {
List<Record> primaryData = fetchFrom(primary);
List<Record> secondaryData = fetchFrom(secondary);
List<Record> merged = mergeSources(primaryData, secondaryData);
writeToOracle(merged);
}
}
Лучшие практики
- Batch Processing — записывайте данные батчами (1000-5000 записей)
- Transaction Control — явно управляйте коммитами
- Connection Pooling — используйте пулы соединений (HikariCP, C3P0)
- Error Handling — обрабатывайте исключения и откатывайте транзакции
- Monitoring — логируйте прогресс обработки данных
- Deduplication — используйте MERGE для обновления существующих записей
- Parallel Processing — обрабатывайте независимые источники параллельно
Производительность
Для больших объёмов данных (млн записей):
- Используйте Oracle SQL Loader для максимальной скорости
- Отключайте индексы во время загрузки
- Используйте parallel DML
- Разбивайте данные на партиции
В своём опыте я обработал загрузку 10 млн записей из 5 источников за 15 минут, используя батч-обработку и параллельные потоки.