The point of this project is to explore what a 3-tier web application is like. You can implment it in either Java (and Java frameworks) or Python (and Python frameworks).
Choosing one possible project relations below, you need to create a ListDetails application that allows users to manage their data in a 3-tier architecture.
This means it will have a REST API middle-end, with a relational database backend.
It has three phases.
- build a plan for the project
- design the database schema by building out data objects
- write a SQL file with the schema
- generate another SQL file filled with synthetic generated data that can be loaded into the database
- create a REST server to create, read, update, and delete data objects
- start with
curland doing a GET of your master table - continue with
curland doing a GET of your detail table - add the other CRUD operations for both master and detail tables
- start with
- add a one to many relationship between your master and detail tables
- add REST API endpoints for the one to many relationship
- use a GUI based REST API client to test your endpoints
- you might use Postman or Insomnia, or even Everest.
- add a means to dump and load your data to either SQL and/or JSON files
- create a simple Vanilla JavaScript application to interact with your REST API
- do the same with React
- add web pages for CRUD operations for both master and detail tables
- add web pages for the one to many relationship, designing a UI that shows some dynamic data from the database
A basic SQL lab: tables, schema, selects, and crud in SQL repl; simple API access Java: ListDetail phase 1,2 REST/DB app https://spring.io/guides/gs/accessing-data-rest Spring; Data: ListDetail phase 1,2 REST/DB app (fastapi, flask, sqlite3 https://zcw.guru/kristofer/ae5cb89250b14a6da2903a9cc613390b
A master-detail relationship (sometimes called parent-child relationship) is a fundamental data modeling concept where:
- Master (Parent) Entity: Contains primary information and can exist independently
- Detail (Child) Entity: Contains secondary information that depends on the master entity and cannot exist without it
Understanding master-detail relationships is crucial for several reasons:
- Data Integrity: Ensures related data remains consistent and valid
- Efficient Data Organization: Provides logical structure to complex information
- Improved User Experience: Enables intuitive navigation through hierarchical data
- Optimized Queries: Allows for more efficient database operations
- Scalable Application Design: Creates maintainable, extensible software architecture
- Master: Order
- Detail: Order Items
An order can contain multiple items, but each order item belongs to exactly one order.
- Master: Invoice
- Detail: Line Items
An invoice contains multiple line items, but each line item is associated with exactly one invoice.
- Master: Patient
- Detail: Medical Records
A patient has multiple medical records, but each record belongs to one patient.
- Master: Course
- Detail: Lectures/Assignments
A course consists of multiple lectures and assignments, but each lecture/assignment belongs to one course.
In relational databases, master-detail relationships are typically implemented using foreign keys:
CREATE TABLE orders (
order_id INT PRIMARY KEY,
customer_id INT,
order_date DATE
);
CREATE TABLE order_items (
item_id INT PRIMARY KEY,
order_id INT REFERENCES orders(order_id),
product_id INT,
quantity INT
);
@Entity
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private Date orderDate;
@OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
private List<OrderItem> items = new ArrayList<>();
// Getters and setters
}
@Entity
public class OrderItem {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn(name = "order_id")
private Order order;
private String productName;
private int quantity;
// Getters and setters
}
from sqlalchemy import Column, Integer, String, ForeignKey, Date
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship
Base = declarative_base()
class Order(Base):
__tablename__ = 'orders'
id = Column(Integer, primary_key=True)
order_date = Column(Date)
items = relationship("OrderItem", back_populates="order")
class OrderItem(Base):
__tablename__ = 'order_items'
id = Column(Integer, primary_key=True)
order_id = Column(Integer, ForeignKey('orders.id'))
product_name = Column(String)
quantity = Column(Integer)
order = relationship("Order", back_populates="items")
A well-designed REST API should reflect the master-detail relationship in its endpoints:
/orders- Get all orders/orders/{id}- Get a specific order/orders/{id}/items- Get all items for a specific order/orders/{id}/items/{itemId}- Get a specific item from a specific order
@RestController
@RequestMapping("/api/orders")
public class OrderController {
@Autowired
private OrderService orderService;
@GetMapping
public List<Order> getAllOrders() {
return orderService.findAll();
}
@GetMapping("/{id}")
public Order getOrderById(@PathVariable Long id) {
return orderService.findById(id);
}
@GetMapping("/{id}/items")
public List<OrderItem> getOrderItems(@PathVariable Long id) {
Order order = orderService.findById(id);
return order.getItems();
}
}
from flask import Flask, jsonify
from models import Order, OrderItem
from database import db_session
app = Flask(__name__)
@app.route('/api/orders', methods=['GET'])
def get_all_orders():
orders = Order.query.all()
return jsonify([{'id': o.id, 'order_date': o.order_date} for o in orders])
@app.route('/api/orders/<int:order_id>', methods=['GET'])
def get_order(order_id):
order = Order.query.get_or_404(order_id)
return jsonify({
'id': order.id,
'order_date': order.order_date,
'items': [{'id': item.id, 'product_name': item.product_name} for item in order.items]
})
@app.route('/api/orders/<int:order_id>/items', methods=['GET'])
def get_order_items(order_id):
order = Order.query.get_or_404(order_id)
return jsonify([{'id': item.id, 'product_name': item.product_name} for item in order.items])
- Cascade Operations: Properly configure delete/update cascades
- Indexes: Create appropriate indexes on foreign keys
- Constraints: Implement referential integrity constraints
- Transactions: Use transactions for operations involving both master and detail records
- Pagination: Implement pagination for large detail collections
- Caching: Consider caching frequently accessed master records
Master-detail relationships are the backbone of effective data modeling and application development. Understanding these relationships enables beginners to:
- Design intuitive and efficient data models
- Create scalable database schemas
- Develop user-friendly applications
- Build RESTful APIs that accurately represent business domains
As you progress in your Java or Python development journey, mastering this concept will significantly enhance your ability to model real-world problems and create robust solutions. Whether you're building a simple to-do app or an enterprise-grade system, the master-detail pattern will be a constant companion in your development toolkit.
These are some possible projrct relations for your ListDetail app. You can also propose your own project relations, but it must be approved by an instructor.
- Customer (master) - Orders (detail)
- Department (master) - Employees (detail)
- Course (master) - Students (detail)
- Author (master) - Books (detail)
- Invoice (master) - Line Items (detail)
- Product Category (master) - Products (detail)
- Blog Post (master) - Comments (detail)
- Playlist (master) - Songs (detail)
- Movie (master) - Actors (detail)
- University (master) - Departments (detail)
- Project (master) - Tasks (detail)
- Manufacturer (master) - Products (detail)
- Warehouse (master) - Inventory Items (detail)
- Email (master) - Attachments (detail)
- Country (master) - States/Provinces (detail)
- Hospital (master) - Patients (detail)
- Album (master) - Photos (detail)
- Survey (master) - Questions (detail)