Back to Documentation

Java SDK

Build Java applications with entropyDB using JDBC, JPA, and Spring Data

Overview

The Java SDK provides:

  • JDBC Driver: Standard database connectivity
  • JPA Support: ORM with Hibernate
  • Spring Data: Repository pattern
  • Connection Pooling: HikariCP integration
  • Async Operations: CompletableFuture support

Installation

<!-- Maven -->
<dependency>
    <groupId>com.entropydb</groupId>
    <artifactId>entropydb-jdbc</artifactId>
    <version>1.0.0</version>
</dependency>

<!-- For JPA/Hibernate support -->
<dependency>
    <groupId>com.entropydb</groupId>
    <artifactId>entropydb-hibernate</artifactId>
    <version>1.0.0</version>
</dependency>

<!-- For Spring Data support -->
<dependency>
    <groupId>com.entropydb</groupId>
    <artifactId>entropydb-spring-data</artifactId>
    <version>1.0.0</version>
</dependency>

<!-- Gradle -->
implementation 'com.entropydb:entropydb-jdbc:1.0.0'
implementation 'com.entropydb:entropydb-hibernate:1.0.0'
implementation 'com.entropydb:entropydb-spring-data:1.0.0'

JDBC Connection

import java.sql.*;

public class entropyDBExample {
    private static final String URL = "jdbc:entropydb://localhost:5432/mydb";
    private static final String USER = "admin";
    private static final String PASSWORD = "password";
    
    public static void main(String[] args) {
        // Basic connection
        try (Connection conn = DriverManager.getConnection(URL, USER, PASSWORD)) {
            System.out.println("Connected to entropyDB");
            
            // Create table
            try (Statement stmt = conn.createStatement()) {
                stmt.execute(
                    "CREATE TABLE IF NOT EXISTS users (" +
                    "  id SERIAL PRIMARY KEY," +
                    "  username TEXT NOT NULL," +
                    "  email TEXT UNIQUE," +
                    "  created_at TIMESTAMP DEFAULT NOW()" +
                    ")"
                );
            }
            
            // Insert data with prepared statement
            String insertSQL = "INSERT INTO users (username, email) VALUES (?, ?)";
            try (PreparedStatement pstmt = conn.prepareStatement(insertSQL)) {
                pstmt.setString(1, "alice");
                pstmt.setString(2, "alice@example.com");
                int rows = pstmt.executeUpdate();
                System.out.println(rows + " row(s) inserted");
            }
            
            // Query data
            String selectSQL = "SELECT * FROM users WHERE username = ?";
            try (PreparedStatement pstmt = conn.prepareStatement(selectSQL)) {
                pstmt.setString(1, "alice");
                try (ResultSet rs = pstmt.executeQuery()) {
                    while (rs.next()) {
                        System.out.println("ID: " + rs.getInt("id"));
                        System.out.println("Username: " + rs.getString("username"));
                        System.out.println("Email: " + rs.getString("email"));
                    }
                }
            }
            
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

Connection Pooling (HikariCP)

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import javax.sql.DataSource;

public class ConnectionPool {
    private static HikariDataSource dataSource;
    
    public static DataSource getDataSource() {
        if (dataSource == null) {
            HikariConfig config = new HikariConfig();
            config.setJdbcUrl("jdbc:entropydb://localhost:5432/mydb");
            config.setUsername("admin");
            config.setPassword("password");
            
            // Pool configuration
            config.setMaximumPoolSize(20);
            config.setMinimumIdle(5);
            config.setIdleTimeout(300000);  // 5 minutes
            config.setConnectionTimeout(20000);  // 20 seconds
            config.setMaxLifetime(1200000);  // 20 minutes
            
            // Performance tuning
            config.addDataSourceProperty("cachePrepStmts", "true");
            config.addDataSourceProperty("prepStmtCacheSize", "250");
            config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
            
            dataSource = new HikariDataSource(config);
        }
        return dataSource;
    }
    
    public static void close() {
        if (dataSource != null) {
            dataSource.close();
        }
    }
}

// Usage
try (Connection conn = ConnectionPool.getDataSource().getConnection()) {
    // Use connection
}

JPA / Hibernate

import jakarta.persistence.*;
import java.time.LocalDateTime;

// Entity definition
@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(nullable = false, unique = true)
    private String username;
    
    @Column(unique = true)
    private String email;
    
    @Column(name = "created_at")
    private LocalDateTime createdAt;
    
    // Getters and setters
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    
    public String getUsername() { return username; }
    public void setUsername(String username) { this.username = username; }
    
    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
    
    public LocalDateTime getCreatedAt() { return createdAt; }
    public void setCreatedAt(LocalDateTime createdAt) { this.createdAt = createdAt; }
}

// persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="https://jakarta.ee/xml/ns/persistence" version="3.0">
    <persistence-unit name="entropydb-pu">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        
        <properties>
            <property name="jakarta.persistence.jdbc.driver" value="com.entropydb.jdbc.Driver"/>
            <property name="jakarta.persistence.jdbc.url" value="jdbc:entropydb://localhost:5432/mydb"/>
            <property name="jakarta.persistence.jdbc.user" value="admin"/>
            <property name="jakarta.persistence.jdbc.password" value="password"/>
            
            <property name="hibernate.dialect" value="com.entropydb.hibernate.entropyDBDialect"/>
            <property name="hibernate.hbm2ddl.auto" value="update"/>
            <property name="hibernate.show_sql" value="true"/>
        </properties>
    </persistence-unit>
</persistence>

// Usage
EntityManagerFactory emf = Persistence.createEntityManagerFactory("entropydb-pu");
EntityManager em = emf.createEntityManager();

// Create
em.getTransaction().begin();
User user = new User();
user.setUsername("alice");
user.setEmail("alice@example.com");
user.setCreatedAt(LocalDateTime.now());
em.persist(user);
em.getTransaction().commit();

// Read
User foundUser = em.find(User.class, 1L);

// Query
List<User> users = em.createQuery("SELECT u FROM User u WHERE u.email LIKE :pattern", User.class)
    .setParameter("pattern", "%@example.com")
    .getResultList();

em.close();
emf.close();

Spring Data JPA

// application.yml
spring:
  datasource:
    url: jdbc:entropydb://localhost:5432/mydb
    username: admin
    password: password
    driver-class-name: com.entropydb.jdbc.Driver
    hikari:
      maximum-pool-size: 20
      minimum-idle: 5
  jpa:
    database-platform: com.entropydb.hibernate.entropyDBDialect
    hibernate:
      ddl-auto: update
    show-sql: true

// Repository interface
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Optional;

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    Optional<User> findByUsername(String username);
    List<User> findByEmailContaining(String emailPattern);
    
    @Query("SELECT u FROM User u WHERE u.createdAt > :date")
    List<User> findRecentUsers(@Param("date") LocalDateTime date);
    
    @Query(value = "SELECT * FROM users WHERE email = ?1", nativeQuery = true)
    User findByEmailNative(String email);
}

// Service
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class UserService {
    private final UserRepository userRepository;
    
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
    
    @Transactional
    public User createUser(String username, String email) {
        User user = new User();
        user.setUsername(username);
        user.setEmail(email);
        user.setCreatedAt(LocalDateTime.now());
        return userRepository.save(user);
    }
    
    public Optional<User> findByUsername(String username) {
        return userRepository.findByUsername(username);
    }
    
    public List<User> searchByEmail(String pattern) {
        return userRepository.findByEmailContaining(pattern);
    }
    
    @Transactional
    public void deleteUser(Long id) {
        userRepository.deleteById(id);
    }
}

// Controller
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/users")
public class UserController {
    private final UserService userService;
    
    public UserController(UserService userService) {
        this.userService = userService;
    }
    
    @PostMapping
    public User createUser(@RequestBody UserRequest request) {
        return userService.createUser(request.getUsername(), request.getEmail());
    }
    
    @GetMapping("/{username}")
    public User getUser(@PathVariable String username) {
        return userService.findByUsername(username)
            .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
    }
}

Async Operations

import com.entropydb.async.AsyncConnection;
import java.util.concurrent.CompletableFuture;

public class AsyncExample {
    public static void main(String[] args) {
        AsyncConnection conn = AsyncConnection.create(
            "jdbc:entropydb://localhost:5432/mydb",
            "admin",
            "password"
        );
        
        // Async query
        CompletableFuture<List<User>> usersFuture = conn.query(
            "SELECT * FROM users WHERE created_at > ?",
            LocalDateTime.now().minusDays(7)
        ).thenApply(rs -> {
            List<User> users = new ArrayList<>();
            rs.forEach(row -> {
                User user = new User();
                user.setId(row.getLong("id"));
                user.setUsername(row.getString("username"));
                users.add(user);
            });
            return users;
        });
        
        // Async insert
        CompletableFuture<Integer> insertFuture = conn.execute(
            "INSERT INTO users (username, email) VALUES (?, ?)",
            "bob", "bob@example.com"
        );
        
        // Combine multiple async operations
        CompletableFuture.allOf(usersFuture, insertFuture)
            .thenRun(() -> {
                System.out.println("All operations completed");
                try {
                    List<User> users = usersFuture.get();
                    int rowsAffected = insertFuture.get();
                    System.out.println("Found " + users.size() + " users");
                    System.out.println("Inserted " + rowsAffected + " rows");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            })
            .exceptionally(ex -> {
                System.err.println("Error: " + ex.getMessage());
                return null;
            });
        
        conn.close();
    }
}

Best Practices

Performance

  • • Use connection pooling (HikariCP)
  • • Enable prepared statement caching
  • • Batch operations when possible
  • • Use appropriate fetch sizes

Security

  • • Always use prepared statements
  • • Never concatenate SQL strings
  • • Use SSL connections in production
  • • Implement proper exception handling

Next Steps