⚠️ University Project Notice This framework was developed as part of a university project. It is in no way production-ready, feature-complete, or optimized for performance. It is intended solely for educational purposes and should not be used in any production environment.
- What is an ORM?
- Configure the Database Connection
- Create Entity Classes
- Create a Repository Interface
- Instantiate the Repository
- Built-in Repository Methods
- Dynamic Proxy & Custom Query Methods
An Object-Relational Mapping (ORM) framework is a programming abstraction that simplifies interaction with relational databases. It allows developers to perform database operations using the constructs of their programming language rather than writing raw SQL. The ORM maps Java objects to database tables and back, abstracting away the low-level data access layer.
This makes development more efficient and produces more maintainable code, as complex SQL statements are expressed as readable method calls on typed objects.
Set your connection details in the DatabaseConnection class to establish a connection to your database.
public class DatabaseConnection {
private static final String URL = "jdbc:mysql://<HOST>:<PORT>/<DATABASE_NAME>";
private static final String USER = "<USERNAME>";
private static final String PASSWORD = "<PASSWORD>";
}An entity class represents a table in the database. The framework uses the following annotations to define the mapping:
| Annotation | Description |
|---|---|
@Entity(tableName = "...") |
Marks the class as a database entity and maps it to the specified table. |
@Id(name = "...") |
Marks the primary key field. name refers to the corresponding database column. |
@Column(name = "...") |
Maps a field to a specific database column. |
@JoinColumn(name = "...", referencedColumnName = "...") |
Defines a foreign key relationship to another entity. |
@CompositeKey(keyColumns = {...}) |
Defines a composite primary key spanning multiple columns. |
⚠️ Important: Every entity class must include a no-argument constructor. The framework relies on it for reflective instantiation.
@Entity(tableName = "user")
public class UserEntity {
@Id(name = "user_id")
private int id;
@Column(name = "username")
private String username;
@JoinColumn(name = "address_id", referencedColumnName = "address_id")
private AddressEntity address;
// Required no-args constructor
public UserEntity() {}
// Getters and setters
}@Entity(tableName = "order_item")
@CompositeKey(keyColumns = {"order_id", "product_id"})
public class OrderItemEntity {
@Id(name = "order_id")
private String orderId;
@Id(name = "product_id")
private String productId;
@Column(name = "quantity")
private int quantity;
// Required no-args constructor
public OrderItemEntity() {}
// Getters and setters
}For each entity, define a repository interface that extends Repository<T, ID>, where T is the entity type and ID is the type of the primary key.
public interface UserRepository extends Repository<UserEntity, Integer> {
}The framework will automatically provide implementations of the standard CRUD methods at runtime via Java Dynamic Proxy.
Repository instances are created through RepositoryProxy.newInstance(). No manual implementation is required.
UserRepository userRepository = RepositoryProxy.newInstance(UserRepository.class);Every repository automatically provides the following standard operations:
| Method | Description |
|---|---|
insert(T entity) |
Inserts a new entity record into the database. |
findById(ID id) |
Retrieves an entity by its primary key. |
findAll() |
Retrieves all entity records from the database. |
update(T entity) |
Updates an existing entity record. |
delete(ID id) |
Deletes an entity record by its primary key. |
All find...() methods support optional chaining via .where() and .join() for filtering and joining results, respectively.
UserEntity user = userRepository.findById(1).findOne();UserEntity user = new UserEntity();
user.setUsername("john_doe");
userRepository.insert(user);UserEntity user = userRepository.findAll().where("username", "john_doe");OrderItemRepository orderItemRepository = RepositoryProxy.newInstance(OrderItemRepository.class);
Map<String, Object> compositeKey = new HashMap<>();
compositeKey.put("order_id", "42");
compositeKey.put("product_id", "7");
OrderItemEntity item = orderItemRepository.findById(compositeKey).findOne();String sql = "SELECT * FROM user WHERE username = ?";
UserEntity user = userRepository.executeCustomQuery(sql, "john_doe");The framework leverages Java Dynamic Proxy to interpret method signatures defined in a repository interface and translate them into SQL queries at runtime — without requiring any manual implementation.
To define a custom query method, declare it in the repository interface following the findBy<ColumnName> naming convention:
public interface UserRepository extends Repository<UserEntity, Integer> {
UserEntity findByUsername(String username);
}The proxy will parse the method name, derive the corresponding column and condition, and execute the appropriate SQL query automatically:
UserEntity user = userRepository.findByUsername("john_doe");