CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-springframework--spring

Comprehensive application framework and inversion of control container for the Java platform providing dependency injection, AOP, data access, transaction management, and web framework capabilities

Overview
Eval results
Files

data-access.mddocs/

Data Access & Transaction Management

Spring provides comprehensive data access support including JDBC abstraction, transaction management, and integration with ORM frameworks like Hibernate and JPA. This includes spring-jdbc, spring-tx, spring-orm, and spring-r2dbc modules.

Maven Dependencies

<!-- Spring JDBC -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.3.39</version>
</dependency>

<!-- Spring Transaction Management -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
    <version>5.3.39</version>
</dependency>

<!-- Spring ORM -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-orm</artifactId>
    <version>5.3.39</version>
</dependency>

<!-- Spring R2DBC (Reactive) -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-r2dbc</artifactId>
    <version>5.3.39</version>
</dependency>

<!-- Database driver (example: H2) -->
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <version>2.1.214</version>
</dependency>

Core Imports

// JDBC Core
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.NamedParameterJdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.core.PreparedStatementSetter;

// Data Source
import javax.sql.DataSource;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

// Transaction Management
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.annotation.EnableTransactionManagement;

// ORM Integration
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalEntityManagerFactoryBean;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;

// Exception Translation
import org.springframework.dao.DataAccessException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.dao.DuplicateKeyException;

// R2DBC (Reactive)
import org.springframework.r2dbc.core.DatabaseClient;
import org.springframework.data.r2dbc.config.AbstractR2dbcConfiguration;

JDBC Support

JdbcTemplate

// Central class in JDBC core package providing JDBC operations
public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {
    
    // Query methods
    public <T> T queryForObject(String sql, Class<T> requiredType);
    public <T> T queryForObject(String sql, Class<T> requiredType, Object... args);
    public <T> T queryForObject(String sql, RowMapper<T> rowMapper, Object... args);
    public <T> List<T> query(String sql, RowMapper<T> rowMapper);
    public <T> List<T> query(String sql, RowMapper<T> rowMapper, Object... args);
    public <T> List<T> query(String sql, PreparedStatementSetter pss, RowMapper<T> rowMapper);
    public <T> T query(String sql, ResultSetExtractor<T> rse);
    
    // Update methods
    public int update(String sql);
    public int update(String sql, Object... args);
    public int update(String sql, PreparedStatementSetter pss);
    public int update(PreparedStatementCreator psc);
    
    // Batch operations
    public int[] batchUpdate(String sql, List<Object[]> batchArgs);
    public int[] batchUpdate(String sql, BatchPreparedStatementSetter pss);
    
    // Execute methods
    public void execute(String sql);
    public <T> T execute(PreparedStatementCreator psc, PreparedStatementCallback<T> action);
}

// RowMapper interface for mapping rows of ResultSet
@FunctionalInterface
public interface RowMapper<T> {
    T mapRow(ResultSet rs, int rowNum) throws SQLException;
}

// Interface used by JdbcTemplate for extracting values from ResultSet  
@FunctionalInterface
public interface ResultSetExtractor<T> {
    T extractData(ResultSet rs) throws SQLException, DataAccessException;
}

// Interface for setting values on PreparedStatement
@FunctionalInterface
public interface PreparedStatementSetter {
    void setValues(PreparedStatement ps) throws SQLException;
}

NamedParameterJdbcTemplate

// Template class with support for named parameters
public class NamedParameterJdbcTemplate implements NamedParameterJdbcOperations {
    
    public NamedParameterJdbcTemplate(DataSource dataSource);
    public NamedParameterJdbcTemplate(JdbcOperations classicJdbcTemplate);
    
    // Query methods with named parameters
    public <T> T queryForObject(String sql, Map<String, ?> paramMap, Class<T> requiredType);
    public <T> T queryForObject(String sql, SqlParameterSource paramSource, Class<T> requiredType);
    public <T> T queryForObject(String sql, Map<String, ?> paramMap, RowMapper<T> rowMapper);
    public <T> List<T> query(String sql, Map<String, ?> paramMap, RowMapper<T> rowMapper);
    public <T> List<T> query(String sql, SqlParameterSource paramSource, RowMapper<T> rowMapper);
    
    // Update methods with named parameters
    public int update(String sql, Map<String, ?> paramMap);
    public int update(String sql, SqlParameterSource paramSource);
    
    // Batch operations
    public int[] batchUpdate(String sql, Map<String, ?>[] batchValues);
    public int[] batchUpdate(String sql, SqlParameterSource[] batchArgs);
}

// Interface for parameter sources
public interface SqlParameterSource {
    boolean hasValue(String paramName);
    Object getValue(String paramName) throws IllegalArgumentException;
    int getSqlType(String paramName);
    String getTypeName(String paramName);
    String[] getParameterNames();
}

// Map-based parameter source
public class MapSqlParameterSource implements SqlParameterSource {
    public MapSqlParameterSource();
    public MapSqlParameterSource(String paramName, Object value);
    public MapSqlParameterSource(Map<String, ?> values);
    
    public MapSqlParameterSource addValue(String paramName, Object value);
    public MapSqlParameterSource addValue(String paramName, Object value, int sqlType);
    public MapSqlParameterSource addValues(Map<String, ?> values);
}

Transaction Management

Core Transaction Interfaces

// Central interface for transaction management
public interface PlatformTransactionManager {
    TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;
    void commit(TransactionStatus status) throws TransactionException;
    void rollback(TransactionStatus status) throws TransactionException;
}

// Interface that defines Spring-compliant transaction properties
public interface TransactionDefinition {
    int PROPAGATION_REQUIRED = 0;
    int PROPAGATION_SUPPORTS = 1;
    int PROPAGATION_MANDATORY = 2;
    int PROPAGATION_REQUIRES_NEW = 3;
    int PROPAGATION_NOT_SUPPORTED = 4;
    int PROPAGATION_NEVER = 5;
    int PROPAGATION_NESTED = 6;
    
    int ISOLATION_DEFAULT = -1;
    int ISOLATION_READ_UNCOMMITTED = 1;
    int ISOLATION_READ_COMMITTED = 2;
    int ISOLATION_REPEATABLE_READ = 4;
    int ISOLATION_SERIALIZABLE = 8;
    
    int TIMEOUT_DEFAULT = -1;
    
    int getPropagationBehavior();
    int getIsolationLevel();
    int getTimeout();
    boolean isReadOnly();
    String getName();
}

// Representation of status of transaction
public interface TransactionStatus extends SavepointManager, Flushable {
    boolean isNewTransaction();
    boolean hasSavepoint();
    void setRollbackOnly();
    boolean isRollbackOnly();
    boolean isCompleted();
}

// Template class that simplifies programmatic transaction demarcation
public class TransactionTemplate extends DefaultTransactionDefinition implements TransactionOperations, InitializingBean {
    
    public TransactionTemplate();
    public TransactionTemplate(PlatformTransactionManager transactionManager);
    
    public <T> T execute(TransactionCallback<T> action) throws TransactionException;
    public void execute(TransactionCallbackWithoutResult action) throws TransactionException;
}

Declarative Transactions

// Describes transaction attributes on individual methods or classes
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {
    
    @AliasFor("transactionManager")
    String value() default "";
    
    String transactionManager() default "";
    
    Propagation propagation() default Propagation.REQUIRED;
    
    Isolation isolation() default Isolation.DEFAULT;
    
    int timeout() default TransactionDefinition.TIMEOUT_DEFAULT;
    
    boolean readOnly() default false;
    
    Class<? extends Throwable>[] rollbackFor() default {};
    
    String[] rollbackForClassName() default {};
    
    Class<? extends Throwable>[] noRollbackFor() default {};
    
    String[] noRollbackForClassName() default {};
}

// Enables Spring's annotation-driven transaction management capability
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
    boolean proxyTargetClass() default false;
    AdviceMode mode() default AdviceMode.PROXY;
    int order() default Ordered.LOWEST_PRECEDENCE;
}

// Propagation enum
public enum Propagation {
    REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED),
    SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS),
    MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY),
    REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW),
    NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED),
    NEVER(TransactionDefinition.PROPAGATION_NEVER),
    NESTED(TransactionDefinition.PROPAGATION_NESTED);
}

// Isolation enum
public enum Isolation {
    DEFAULT(TransactionDefinition.ISOLATION_DEFAULT),
    READ_UNCOMMITTED(TransactionDefinition.ISOLATION_READ_UNCOMMITTED),
    READ_COMMITTED(TransactionDefinition.ISOLATION_READ_COMMITTED),
    REPEATABLE_READ(TransactionDefinition.ISOLATION_REPEATABLE_READ),
    SERIALIZABLE(TransactionDefinition.ISOLATION_SERIALIZABLE);
}

Transaction Managers

// PlatformTransactionManager implementation for single JDBC DataSource
public class DataSourceTransactionManager extends AbstractPlatformTransactionManager 
        implements ResourceTransactionManager, InitializingBean {
    
    public DataSourceTransactionManager();
    public DataSourceTransactionManager(DataSource dataSource);
    
    public void setDataSource(DataSource dataSource);
    public DataSource getDataSource();
    public void setEnforceReadOnly(boolean enforceReadOnly);
}

// PlatformTransactionManager for JPA EntityManagerFactory
public class JpaTransactionManager extends AbstractPlatformTransactionManager 
        implements ResourceTransactionManager, BeanFactoryAware, InitializingBean {
    
    public JpaTransactionManager();
    public JpaTransactionManager(EntityManagerFactory emf);
    
    public void setEntityManagerFactory(EntityManagerFactory emf);
    public EntityManagerFactory getEntityManagerFactory();
    public void setDataSource(DataSource dataSource);
}

// PlatformTransactionManager for Hibernate SessionFactory
public class HibernateTransactionManager extends AbstractPlatformTransactionManager 
        implements ResourceTransactionManager, BeanFactoryAware, InitializingBean {
    
    public HibernateTransactionManager();
    public HibernateTransactionManager(SessionFactory sessionFactory);
    
    public void setSessionFactory(SessionFactory sessionFactory);
    public SessionFactory getSessionFactory();
    public void setDataSource(DataSource dataSource);
}

ORM Integration

JPA Integration

// FactoryBean for creating JPA EntityManagerFactory
public class LocalEntityManagerFactoryBean extends AbstractEntityManagerFactoryBean {
    
    public void setPersistenceUnitName(String persistenceUnitName);
    public void setPersistenceUnitPostProcessors(PersistenceUnitPostProcessor... postProcessors);
    
    @Override
    protected EntityManagerFactory createNativeEntityManagerFactory() throws PersistenceException;
}

// Extended EntityManagerFactory interface for container integration
public class LocalContainerEntityManagerFactoryBean extends AbstractEntityManagerFactoryBean 
        implements ResourceLoaderAware, LoadTimeWeaverAware {
    
    public void setDataSource(DataSource dataSource);
    public void setPackagesToScan(String... packagesToScan);
    public void setJpaVendorAdapter(JpaVendorAdapter jpaVendorAdapter);
    public void setJpaProperties(Properties jpaProperties);
}

// JPA Vendor Adapter for Hibernate
public class HibernateJpaVendorAdapter extends AbstractJpaVendorAdapter {
    public void setDatabase(Database database);
    public void setDatabasePlatform(String databasePlatform);
    public void setGenerateDdl(boolean generateDdl);
    public void setShowSql(boolean showSql);
}

Hibernate Integration

// FactoryBean for creating Hibernate SessionFactory
public class LocalSessionFactoryBean extends HibernateExceptionTranslator 
        implements FactoryBean<SessionFactory>, ResourceLoaderAware, InitializingBean, DisposableBean {
    
    public void setDataSource(DataSource dataSource);
    public void setPackagesToScan(String... packagesToScan);
    public void setAnnotatedClasses(Class<?>... annotatedClasses);
    public void setHibernateProperties(Properties hibernateProperties);
    public void setConfigLocation(Resource configLocation);
}

// Helper class for Hibernate data access (legacy approach)
public class HibernateTemplate extends HibernateAccessor implements HibernateOperations {
    
    public HibernateTemplate();
    public HibernateTemplate(SessionFactory sessionFactory);
    
    // CRUD operations
    public void save(Object entity);
    public void update(Object entity);
    public void saveOrUpdate(Object entity);
    public void delete(Object entity);
    public <T> T get(Class<T> entityClass, Serializable id);
    public <T> T load(Class<T> entityClass, Serializable id);
    
    // Query operations
    public List<?> find(String queryString, Object... values);
    public <T> List<T> findByNamedParam(String queryString, String[] paramNames, Object[] values);
}

Reactive Data Access (R2DBC)

R2DBC Support

// Configuration base class for R2DBC
public abstract class AbstractR2dbcConfiguration {
    
    @Bean
    public abstract ConnectionFactory connectionFactory();
    
    @Bean
    public R2dbcTransactionManager transactionManager() {
        return new R2dbcTransactionManager(connectionFactory());
    }
    
    @Bean
    public DatabaseClient databaseClient() {
        return DatabaseClient.builder()
            .connectionFactory(connectionFactory())
            .build();
    }
}

// Reactive database client
public interface DatabaseClient {
    
    GenericExecuteSpec sql(String sql);
    GenericExecuteSpec sql(Supplier<String> sqlSupplier);
    
    // Execute spec for generic SQL operations
    interface GenericExecuteSpec {
        GenericExecuteSpec bind(Object identifier, Object value);
        GenericExecuteSpec bind(int index, Object value);
        GenericExecuteSpec bindNull(Object identifier, Class<?> type);
        
        FetchSpec<Map<String, Object>> fetch();
        <T> FetchSpec<T> map(Function<Row, T> mappingFunction);
        <T> FetchSpec<T> map(BiFunction<Row, RowMetadata, T> mappingFunction);
        
        Mono<Void> then();
    }
    
    // Fetch specification
    interface FetchSpec<T> {
        Mono<T> one();
        Mono<T> first();
        Flux<T> all();
        Mono<Long> rowsUpdated();
    }
}

// R2DBC Transaction Manager
public class R2dbcTransactionManager extends AbstractReactiveTransactionManager 
        implements ResourceTransactionManager, InitializingBean {
    
    public R2dbcTransactionManager(ConnectionFactory connectionFactory);
    public void setConnectionFactory(ConnectionFactory connectionFactory);
    public ConnectionFactory getConnectionFactory();
}

Practical Usage Examples

Basic JDBC Operations

@Repository
public class UserRepository {
    
    private final JdbcTemplate jdbcTemplate;
    
    public UserRepository(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }
    
    // Simple query for object
    public User findById(Long id) {
        String sql = "SELECT id, username, email, created_date FROM users WHERE id = ?";
        return jdbcTemplate.queryForObject(sql, new UserRowMapper(), id);
    }
    
    // Query for list
    public List<User> findByEmail(String email) {
        String sql = "SELECT id, username, email, created_date FROM users WHERE email LIKE ?";
        return jdbcTemplate.query(sql, new UserRowMapper(), "%" + email + "%");
    }
    
    // Insert operation
    public void save(User user) {
        String sql = "INSERT INTO users (username, email, created_date) VALUES (?, ?, ?)";
        jdbcTemplate.update(sql, user.getUsername(), user.getEmail(), user.getCreatedDate());
    }
    
    // Update operation
    public void update(User user) {
        String sql = "UPDATE users SET username = ?, email = ? WHERE id = ?";
        int rowsAffected = jdbcTemplate.update(sql, user.getUsername(), user.getEmail(), user.getId());
        
        if (rowsAffected == 0) {
            throw new EmptyResultDataAccessException("User not found: " + user.getId(), 1);
        }
    }
    
    // Delete operation
    public void delete(Long id) {
        String sql = "DELETE FROM users WHERE id = ?";
        jdbcTemplate.update(sql, id);
    }
    
    // Custom RowMapper
    private static class UserRowMapper implements RowMapper<User> {
        @Override
        public User mapRow(ResultSet rs, int rowNum) throws SQLException {
            User user = new User();
            user.setId(rs.getLong("id"));
            user.setUsername(rs.getString("username"));
            user.setEmail(rs.getString("email"));
            user.setCreatedDate(rs.getTimestamp("created_date").toLocalDateTime());
            return user;
        }
    }
}

Named Parameter Operations

@Repository
public class OrderRepository {
    
    private final NamedParameterJdbcTemplate namedParameterJdbcTemplate;
    
    public OrderRepository(NamedParameterJdbcTemplate namedParameterJdbcTemplate) {
        this.namedParameterJdbcTemplate = namedParameterJdbcTemplate;
    }
    
    // Named parameters with Map
    public List<Order> findByUserId(Long userId) {
        String sql = "SELECT id, user_id, total_amount, order_date FROM orders WHERE user_id = :userId";
        
        Map<String, Object> params = new HashMap<>();
        params.put("userId", userId);
        
        return namedParameterJdbcTemplate.query(sql, params, new OrderRowMapper());
    }
    
    // Named parameters with MapSqlParameterSource
    public void save(Order order) {
        String sql = "INSERT INTO orders (user_id, total_amount, order_date) VALUES (:userId, :totalAmount, :orderDate)";
        
        MapSqlParameterSource params = new MapSqlParameterSource()
            .addValue("userId", order.getUserId())
            .addValue("totalAmount", order.getTotalAmount())
            .addValue("orderDate", order.getOrderDate());
        
        namedParameterJdbcTemplate.update(sql, params);
    }
    
    // Batch operations
    public void saveBatch(List<Order> orders) {
        String sql = "INSERT INTO orders (user_id, total_amount, order_date) VALUES (:userId, :totalAmount, :orderDate)";
        
        SqlParameterSource[] batchParams = orders.stream()
            .map(order -> new MapSqlParameterSource()
                .addValue("userId", order.getUserId())
                .addValue("totalAmount", order.getTotalAmount())
                .addValue("orderDate", order.getOrderDate()))
            .toArray(SqlParameterSource[]::new);
        
        namedParameterJdbcTemplate.batchUpdate(sql, batchParams);
    }
    
    // Complex queries with multiple parameters
    public List<Order> findOrdersByDateRange(LocalDateTime startDate, LocalDateTime endDate, OrderStatus status) {
        String sql = """
            SELECT id, user_id, total_amount, order_date, status 
            FROM orders 
            WHERE order_date BETWEEN :startDate AND :endDate 
            AND status = :status
            ORDER BY order_date DESC
            """;
        
        MapSqlParameterSource params = new MapSqlParameterSource()
            .addValue("startDate", startDate)
            .addValue("endDate", endDate)
            .addValue("status", status.name());
        
        return namedParameterJdbcTemplate.query(sql, params, new OrderRowMapper());
    }
}

Transaction Management

// Configuration
@Configuration
@EnableTransactionManagement
public class DatabaseConfig {
    
    @Bean
    public DataSource dataSource() {
        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setJdbcUrl("jdbc:postgresql://localhost:5432/mydb");
        dataSource.setUsername("user");
        dataSource.setPassword("password");
        dataSource.setMaximumPoolSize(20);
        return dataSource;
    }
    
    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
    
    @Bean
    public JdbcTemplate jdbcTemplate(DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }
}

// Service with declarative transactions
@Service
public class OrderService {
    
    private final OrderRepository orderRepository;
    private final PaymentService paymentService;
    private final EmailService emailService;
    
    public OrderService(OrderRepository orderRepository, PaymentService paymentService, EmailService emailService) {
        this.orderRepository = orderRepository;
        this.paymentService = paymentService;
        this.emailService = emailService;
    }
    
    @Transactional
    public Order createOrder(Order order) {
        // Save order
        Order savedOrder = orderRepository.save(order);
        
        // Process payment
        Payment payment = paymentService.processPayment(savedOrder);
        
        // Send confirmation email
        emailService.sendOrderConfirmation(savedOrder);
        
        return savedOrder;
    }
    
    @Transactional(readOnly = true)
    public List<Order> getUserOrders(Long userId) {
        return orderRepository.findByUserId(userId);
    }
    
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void cancelOrder(Long orderId) {
        Order order = orderRepository.findById(orderId);
        
        if (order.getStatus() == OrderStatus.CONFIRMED) {
            paymentService.refundPayment(order.getPaymentId());
            order.setStatus(OrderStatus.CANCELLED);
            orderRepository.update(order);
            
            emailService.sendCancellationNotification(order);
        }
    }
    
    @Transactional(rollbackFor = {PaymentException.class, EmailException.class})
    public void processOrderWithStrictRollback(Order order) {
        orderRepository.save(order);
        paymentService.processPayment(order); // Throws PaymentException
        emailService.sendConfirmation(order); // Throws EmailException
    }
    
    // Custom transaction attributes
    @Transactional(
        isolation = Isolation.REPEATABLE_READ,
        timeout = 30,
        rollbackFor = Exception.class
    )
    public void complexOrderProcessing(Order order) {
        // Complex business logic with specific transaction requirements
    }
}

Programmatic Transactions

@Service
public class AccountService {
    
    private final AccountRepository accountRepository;
    private final TransactionTemplate transactionTemplate;
    
    public AccountService(AccountRepository accountRepository, PlatformTransactionManager transactionManager) {
        this.accountRepository = accountRepository;
        this.transactionTemplate = new TransactionTemplate(transactionManager);
    }
    
    public void transferMoney(Long fromAccountId, Long toAccountId, BigDecimal amount) {
        transactionTemplate.execute(status -> {
            try {
                Account fromAccount = accountRepository.findById(fromAccountId);
                Account toAccount = accountRepository.findById(toAccountId);
                
                if (fromAccount.getBalance().compareTo(amount) < 0) {
                    throw new InsufficientFundsException("Not enough funds");
                }
                
                fromAccount.setBalance(fromAccount.getBalance().subtract(amount));
                toAccount.setBalance(toAccount.getBalance().add(amount));
                
                accountRepository.update(fromAccount);
                accountRepository.update(toAccount);
                
                return null; // TransactionCallbackWithoutResult
                
            } catch (Exception e) {
                status.setRollbackOnly();
                throw e;
            }
        });
    }
    
    // With return value
    public Account createAccountWithInitialDeposit(String accountNumber, BigDecimal initialDeposit) {
        return transactionTemplate.execute(status -> {
            Account account = new Account();
            account.setAccountNumber(accountNumber);
            account.setBalance(initialDeposit);
            
            Long accountId = accountRepository.save(account);
            account.setId(accountId);
            
            // Log transaction
            auditService.logAccountCreation(account);
            
            return account;
        });
    }
    
    // Custom transaction definition
    public void performOperationWithCustomTransaction() {
        DefaultTransactionDefinition txDef = new DefaultTransactionDefinition();
        txDef.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
        txDef.setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE);
        txDef.setTimeout(30);
        
        TransactionTemplate customTemplate = new TransactionTemplate(transactionManager, txDef);
        
        customTemplate.execute(status -> {
            // Custom transaction logic
            return null;
        });
    }
}

JPA Integration

// JPA Configuration
@Configuration
@EnableJpaRepositories(basePackages = "com.example.repository")
@EnableTransactionManagement
public class JpaConfig {
    
    @Bean
    public DataSource dataSource() {
        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setJdbcUrl("jdbc:postgresql://localhost:5432/mydb");
        dataSource.setUsername("user");
        dataSource.setPassword("password");
        return dataSource;
    }
    
    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
        LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
        em.setDataSource(dataSource());
        em.setPackagesToScan("com.example.entity");
        
        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        vendorAdapter.setGenerateDdl(true);
        vendorAdapter.setShowSql(true);
        em.setJpaVendorAdapter(vendorAdapter);
        
        Properties properties = new Properties();
        properties.setProperty("hibernate.hbm2ddl.auto", "update");
        properties.setProperty("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect");
        em.setJpaProperties(properties);
        
        return em;
    }
    
    @Bean
    public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(emf);
        return transactionManager;
    }
}

// JPA Entity
@Entity
@Table(name = "users")
public class User {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(name = "username", nullable = false, unique = true)
    private String username;
    
    @Column(name = "email", nullable = false)
    private String email;
    
    @Column(name = "created_date")
    private LocalDateTime createdDate;
    
    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List<Order> orders = new ArrayList<>();
    
    // Constructors, getters, setters
}

// Repository using EntityManager directly
@Repository
public class UserJpaRepository {
    
    @PersistenceContext
    private EntityManager entityManager;
    
    public User save(User user) {
        if (user.getId() == null) {
            entityManager.persist(user);
            return user;
        } else {
            return entityManager.merge(user);
        }
    }
    
    public User findById(Long id) {
        return entityManager.find(User.class, id);
    }
    
    public List<User> findByUsername(String username) {
        TypedQuery<User> query = entityManager.createQuery(
            "SELECT u FROM User u WHERE u.username LIKE :username", User.class);
        query.setParameter("username", "%" + username + "%");
        return query.getResultList();
    }
    
    public void delete(User user) {
        if (entityManager.contains(user)) {
            entityManager.remove(user);
        } else {
            entityManager.remove(entityManager.merge(user));
        }
    }
    
    // Native query example
    @SuppressWarnings("unchecked")
    public List<User> findUsersWithOrdersInDateRange(LocalDate startDate, LocalDate endDate) {
        Query query = entityManager.createNativeQuery(
            "SELECT DISTINCT u.* FROM users u " +
            "JOIN orders o ON u.id = o.user_id " + 
            "WHERE o.order_date BETWEEN ?1 AND ?2", User.class);
        
        query.setParameter(1, startDate);
        query.setParameter(2, endDate);
        
        return query.getResultList();
    }
}

R2DBC Reactive Data Access

// R2DBC Configuration
@Configuration
@EnableR2dbcRepositories
public class R2dbcConfig extends AbstractR2dbcConfiguration {
    
    @Override
    @Bean
    public ConnectionFactory connectionFactory() {
        return ConnectionFactories.get(ConnectionFactoryOptions.builder()
            .option(DRIVER, "postgresql")
            .option(HOST, "localhost")
            .option(PORT, 5432)
            .option(USER, "user")
            .option(PASSWORD, "password")
            .option(DATABASE, "mydb")
            .build());
    }
    
    @Bean
    public R2dbcEntityTemplate r2dbcEntityTemplate(DatabaseClient databaseClient) {
        return new R2dbcEntityTemplate(databaseClient);
    }
}

// Reactive Repository
@Repository
public class ReactiveUserRepository {
    
    private final DatabaseClient databaseClient;
    
    public ReactiveUserRepository(DatabaseClient databaseClient) {
        this.databaseClient = databaseClient;
    }
    
    public Mono<User> findById(Long id) {
        return databaseClient
            .sql("SELECT id, username, email, created_date FROM users WHERE id = :id")
            .bind("id", id)
            .map((row, metadata) -> {
                User user = new User();
                user.setId(row.get("id", Long.class));
                user.setUsername(row.get("username", String.class));
                user.setEmail(row.get("email", String.class));
                user.setCreatedDate(row.get("created_date", LocalDateTime.class));
                return user;
            })
            .one();
    }
    
    public Flux<User> findAll() {
        return databaseClient
            .sql("SELECT id, username, email, created_date FROM users ORDER BY created_date DESC")
            .map(this::mapUser)
            .all();
    }
    
    public Mono<User> save(User user) {
        if (user.getId() == null) {
            return databaseClient
                .sql("INSERT INTO users (username, email, created_date) VALUES (:username, :email, :createdDate)")
                .bind("username", user.getUsername())
                .bind("email", user.getEmail())
                .bind("createdDate", user.getCreatedDate())
                .fetch()
                .rowsUpdated()
                .map(count -> user);
        } else {
            return databaseClient
                .sql("UPDATE users SET username = :username, email = :email WHERE id = :id")
                .bind("id", user.getId())
                .bind("username", user.getUsername())
                .bind("email", user.getEmail())
                .fetch()
                .rowsUpdated()
                .map(count -> user);
        }
    }
    
    public Mono<Void> deleteById(Long id) {
        return databaseClient
            .sql("DELETE FROM users WHERE id = :id")
            .bind("id", id)
            .then();
    }
    
    private User mapUser(Row row, RowMetadata metadata) {
        User user = new User();
        user.setId(row.get("id", Long.class));
        user.setUsername(row.get("username", String.class));
        user.setEmail(row.get("email", String.class));
        user.setCreatedDate(row.get("created_date", LocalDateTime.class));
        return user;
    }
}

// Reactive Service with Transactions
@Service
public class ReactiveUserService {
    
    private final ReactiveUserRepository userRepository;
    private final R2dbcTransactionManager transactionManager;
    
    public ReactiveUserService(ReactiveUserRepository userRepository, 
                              R2dbcTransactionManager transactionManager) {
        this.userRepository = userRepository;
        this.transactionManager = transactionManager;
    }
    
    @Transactional
    public Mono<User> createUser(User user) {
        return userRepository.save(user)
            .doOnNext(savedUser -> log.info("User created: {}", savedUser.getId()));
    }
    
    public Mono<User> updateUser(Long id, User updatedUser) {
        return userRepository.findById(id)
            .switchIfEmpty(Mono.error(new UserNotFoundException("User not found: " + id)))
            .map(existingUser -> {
                existingUser.setUsername(updatedUser.getUsername());
                existingUser.setEmail(updatedUser.getEmail());
                return existingUser;
            })
            .flatMap(userRepository::save);
    }
    
    // Manual transaction control
    public Mono<Void> performTransactionalOperation(User user1, User user2) {
        TransactionalOperator operator = TransactionalOperator.create(transactionManager);
        
        return userRepository.save(user1)
            .then(userRepository.save(user2))
            .then()
            .as(operator::transactional);
    }
}

Exception Handling

DAO Exception Hierarchy

// Common exception handling patterns
@Service
public class UserService {
    
    private final UserRepository userRepository;
    
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
    
    public User getUserById(Long id) {
        try {
            return userRepository.findById(id);
        } catch (EmptyResultDataAccessException e) {
            throw new UserNotFoundException("User not found with id: " + id);
        } catch (DataIntegrityViolationException e) {
            throw new UserServiceException("Data integrity violation", e);
        } catch (DataAccessException e) {
            throw new UserServiceException("Database access error", e);
        }
    }
    
    public User createUser(User user) {
        try {
            return userRepository.save(user);
        } catch (DuplicateKeyException e) {
            throw new UserAlreadyExistsException("User already exists: " + user.getUsername());
        } catch (DataAccessException e) {
            throw new UserServiceException("Failed to create user", e);
        }
    }
}

Spring's data access support provides a comprehensive foundation for working with databases, offering both traditional JDBC operations and modern reactive programming models, all integrated with robust transaction management capabilities.

Install with Tessl CLI

npx tessl i tessl/maven-org-springframework--spring

docs

aop.md

core-container.md

data-access.md

index.md

integration.md

messaging.md

reactive-web.md

testing.md

web-framework.md

tile.json