277 lines
11 KiB
Markdown
277 lines
11 KiB
Markdown
# Database Guidelines
|
|
|
|
> MySQL data and DAO conventions for the library-management system.
|
|
|
|
---
|
|
|
|
## Overview
|
|
|
|
MySQL is the project data layer. DAO classes perform CRUD and query operations
|
|
against MySQL. The initial scaffold schema exists at
|
|
`src/main/resources/db/schema.sql`; future module tables should follow the same
|
|
DDL style and DAO boundaries.
|
|
|
|
---
|
|
|
|
## Core Tables
|
|
|
|
Use primary keys for every table and foreign keys for cross-entity integrity.
|
|
|
|
Implemented scaffold tables:
|
|
|
|
- `roles`: administrator, librarian, reader, and future role definitions.
|
|
- `permissions`: permission definitions for protected actions.
|
|
- `role_permissions`: role-to-permission mapping.
|
|
- `users`: login accounts for administrator, librarian, and reader roles.
|
|
- `system_logs`: key operation logs, backup events, and exception traces.
|
|
- `book_categories`: category names and descriptions for catalog grouping.
|
|
- `books`: book information, category reference, inventory counts, and catalog
|
|
status.
|
|
|
|
Planned module tables:
|
|
|
|
- `readers`: reader profiles, borrowing eligibility, contact information.
|
|
- `borrow_records`: book-reader borrowing, return, renew, and overdue data.
|
|
|
|
Record new schema changes in `src/main/resources/db/schema.sql` and update this
|
|
spec with exact table names, key columns, and DAO/service contracts.
|
|
|
|
---
|
|
|
|
## DAO Responsibilities
|
|
|
|
- DAOs own database CRUD and query details.
|
|
- Use parameterized SQL or prepared-statement style access; never concatenate
|
|
raw request parameters into SQL.
|
|
- Keep transaction boundaries in the service layer for workflows that span
|
|
multiple DAO calls, such as borrow/return operations that also update
|
|
inventory status.
|
|
- Return entities or small query result objects to services, not HTML or
|
|
servlet response objects.
|
|
- Keep MySQL connection details in `src/main/resources/db.properties` loaded by
|
|
`JdbcUtil`. The required keys are `db.driver`, `db.url`, `db.username`, and
|
|
`db.password`.
|
|
|
|
---
|
|
|
|
## Query Guidance
|
|
|
|
- Book search must support combined lookup by title, author, category, and ID.
|
|
- Statistics queries should cover borrowing rankings, inventory reports, and
|
|
overdue reports.
|
|
- Borrowing records should preserve enough dates/status fields for borrow,
|
|
return, renew, overdue calculation, and automatic collection status updates.
|
|
- Permission queries should support role-based checks for administrator,
|
|
librarian, and reader workflows.
|
|
|
|
---
|
|
|
|
## Integrity Constraints
|
|
|
|
- `books.category_id` should reference `book_categories`.
|
|
- `borrow_records.book_id` should reference `books`.
|
|
- `borrow_records.reader_id` should reference `readers`.
|
|
- Administrator-role and role-permission mapping tables should use foreign keys
|
|
to preserve authorization integrity.
|
|
- `users.role_code` must reference `roles.code`.
|
|
- `role_permissions.role_code` must reference `roles.code`.
|
|
- `role_permissions.permission_code` must reference `permissions.code`.
|
|
- `books.status` must match `BookStatus` enum codes: `available`,
|
|
`unavailable`, and `archived`.
|
|
|
|
## Scenario: Book Catalog And Management Slice
|
|
|
|
### 1. Scope / Trigger
|
|
|
|
- Trigger: the first concrete business module introduced catalog search and
|
|
basic book management across MySQL, DAO, service, Servlet, and JSP layers.
|
|
- Schema path: `src/main/resources/db/schema.sql`.
|
|
- JSP paths: `WEB-INF/jsp/books/catalog.jsp`, `books/manage.jsp`, and
|
|
`books/form.jsp`.
|
|
|
|
### 2. Signatures
|
|
|
|
- DAO signatures: `BookDao.findAllCategories()`,
|
|
`BookDao.search(BookSearchCriteria criteria)`, `findById(long id)`,
|
|
`findByIdentifier(String identifier)`, `create(Book book)`,
|
|
`update(Book book)`, and `delete(long id)`.
|
|
- Entity/search signatures: `Book` fields are `id`, `identifier`, `title`,
|
|
`author`, `categoryId`, `categoryName`, `totalCopies`, `availableCopies`,
|
|
`status`, `createdAt`, and `updatedAt`; `BookSearchCriteria` fields are
|
|
`identifier`, `title`, `author`, and nullable `categoryId`.
|
|
- Service signatures: `BookService.listCategories()`,
|
|
`searchBooks(BookSearchCriteria criteria)`, `findBook(long id)`,
|
|
`createBook(AuthenticatedUser actor, Book book)`,
|
|
`updateBook(AuthenticatedUser actor, Book book)`, and
|
|
`deleteBook(AuthenticatedUser actor, long id)`, all returning
|
|
`ServiceResult<T>`.
|
|
- Read route: `GET /catalog` with optional `identifier`, `title`, `author`,
|
|
and `categoryId` query fields.
|
|
- Management routes: `GET /books`, `GET /books/new`, `GET /books/edit?id=...`,
|
|
`POST /books`, `POST /books/update`, and `POST /books/delete`.
|
|
- Protected permissions: `/catalog` requires `VIEW_CATALOG`; `/books*`
|
|
requires `MANAGE_BOOKS`.
|
|
- DB signatures:
|
|
- `book_categories(id, name, description, created_at, updated_at)`, with
|
|
unique key `uk_book_categories_name(name)`.
|
|
- `books(id, book_identifier, title, author, category_id, total_copies,
|
|
available_copies, status, created_at, updated_at)`, with unique key
|
|
`uk_books_identifier(book_identifier)`, indexes on title, author, category,
|
|
and status, foreign key `fk_books_category`, and checks for non-negative
|
|
copy counts and allowed status values.
|
|
|
|
### 3. Contracts
|
|
|
|
- `book_categories.name` is unique and displayed through category selectors.
|
|
- `books.book_identifier` is the unique user-facing book ID.
|
|
- `books.category_id` references `book_categories.id`.
|
|
- `books.total_copies` and `books.available_copies` are non-negative, and
|
|
available copies cannot exceed total copies.
|
|
- `books.status` stores the Java `BookStatus` code exactly.
|
|
- Servlet controllers parse request fields and set JSP attributes such as
|
|
`criteria`, `categories`, `books`, `book`, `statuses`, `errors`,
|
|
`errorMessage`, and `successMessage`.
|
|
- `ServiceResult<T>` is the service-to-controller response contract:
|
|
`successful`, nullable `data`, nullable `message`, and field-level
|
|
`errors`. Controllers must pass validation errors to JSPs so form/search
|
|
redisplay can highlight the exact field, for example `errors.categoryId`.
|
|
- JSP pages render JavaBean properties only; they must not call DAOs or embed
|
|
SQL.
|
|
|
|
### 4. Validation & Error Matrix
|
|
|
|
- Missing identifier, title, author, category, copy counts, or status -> return
|
|
to `books/form.jsp` with field errors.
|
|
- Negative total or available copies -> return a field error.
|
|
- Available copies greater than total copies -> return
|
|
`Available copies cannot exceed total copies.`
|
|
- Duplicate `book_identifier` -> return a field error on `identifier`.
|
|
- Reader or unauthenticated actor attempts write -> HTTP 403 through
|
|
authorization filter or service denial.
|
|
- DAO failure during list/search/write -> log server-side details and return
|
|
`Book service is temporarily unavailable. Please try again later.`
|
|
- Successful create/update/delete -> redirect to `/books` with a short flash
|
|
message.
|
|
|
|
### 5. Good/Base/Bad Cases
|
|
|
|
- Good: a librarian creates `BK-1002`, sees it in `/books`, and readers can
|
|
find it from `/catalog` without write controls.
|
|
- Base: catalog search with no filters lists available records ordered by
|
|
title, author, and identifier.
|
|
- Bad: a JSP opens JDBC, builds SQL from request parameters, or renders a stack
|
|
trace from a failed DAO call.
|
|
|
|
### 6. Tests Required
|
|
|
|
- Run `BookServiceCheck` or equivalent assertions for invalid inventory,
|
|
duplicate identifiers, reader write denial, successful librarian CRUD, search,
|
|
and DAO failure fallback.
|
|
- Run `PermissionPolicyCheck` to confirm readers lack `MANAGE_BOOKS` and retain
|
|
`VIEW_CATALOG`.
|
|
- Scan JSPs for scriptlets and SQL/JDBC references.
|
|
- When Maven/Tomcat dependencies are installed, run `mvn clean package` to
|
|
compile Servlets and package JSP resources.
|
|
|
|
### 7. Wrong vs Correct
|
|
|
|
#### Wrong
|
|
|
|
```text
|
|
books/form.jsp -> JDBC -> INSERT INTO books using request parameters
|
|
```
|
|
|
|
#### Correct
|
|
|
|
```text
|
|
books/form.jsp -> BookManagementServlet -> BookService -> BookDao -> books
|
|
```
|
|
|
|
## Scenario: Login And Permission Scaffold Schema
|
|
|
|
### 1. Scope / Trigger
|
|
|
|
- Trigger: the initial Java Web scaffold introduced a concrete MySQL schema and
|
|
login contract.
|
|
- Schema path: `src/main/resources/db/schema.sql`.
|
|
- Example configuration path: `src/main/resources/db.properties.example`.
|
|
|
|
### 2. Signatures
|
|
|
|
- DAO signature: `UserDao.findActiveByUsername(String username)`.
|
|
- Service signature: `AuthService.authenticate(String username, String password)`.
|
|
- Permission signature: `AuthService.hasPermission(AuthenticatedUser user, Permission permission)`.
|
|
- Servlet route: `POST /login` with `username`, `password`, and optional
|
|
same-application `redirect`.
|
|
- Protected routes: `/dashboard`, `/admin/home`, `/librarian/home`, and
|
|
`/reader/home`.
|
|
- Session keys: `authenticatedUser`, `userRole`, and `userPermissions`.
|
|
- DB config keys: `db.driver`, `db.url`, `db.username`, and `db.password`.
|
|
- Login tables: `roles`, `permissions`, `role_permissions`, `users`, and
|
|
`system_logs`.
|
|
|
|
### 3. Contracts
|
|
|
|
- `users.username`: unique login identifier submitted by `LoginServlet`.
|
|
- `users.password_hash`: PBKDF2 hash in
|
|
`pbkdf2_sha256$iterations$saltBase64$hashBase64` format.
|
|
- `users.role_code`: foreign key to `roles.code`; supported scaffold values
|
|
are `administrator`, `librarian`, and `reader`.
|
|
- `users.active`: only rows with `active = 1` can authenticate.
|
|
- `roles.code`, `permissions.code`, and `role_permissions` must match the Java
|
|
`Role` and `Permission` enum codes exactly.
|
|
- `db.properties` must be local configuration. Commit
|
|
`db.properties.example`, but do not commit real credentials.
|
|
- Session state stores an `AuthenticatedUser` snapshot, role code, and
|
|
permission-code set. It must not store raw passwords or DAO result objects
|
|
with password hashes.
|
|
- Login redirects must stay inside the current application context. Reject
|
|
values that do not start with a single `/` or that contain CR/LF characters.
|
|
|
|
### 4. Validation & Error Matrix
|
|
|
|
- Missing username or password -> request returns to login JSP with
|
|
`Username and password are required.`
|
|
- Unknown user, inactive user, or hash mismatch -> request returns to login JSP
|
|
with `Invalid username or password.`
|
|
- Unsafe or blank redirect -> ignore and route to `/dashboard` after success.
|
|
- Missing `db.properties`, JDBC failure, or unsupported role code -> request
|
|
returns a generic service-unavailable message and logs server-side details.
|
|
- Authenticated user missing a required permission -> HTTP 403 and
|
|
`WEB-INF/jsp/auth/unauthorized.jsp`.
|
|
|
|
### 5. Good/Base/Bad Cases
|
|
|
|
- Good: `admin` resolves to `administrator`, receives all scaffold
|
|
permissions, and can access `/admin/home`.
|
|
- Base: `reader` resolves to `reader`, can access `/reader/home`, and cannot
|
|
access `/admin/home`.
|
|
- Bad: a JSP reads SQL or password hashes directly from the database. Keep that
|
|
logic in DAO/service code.
|
|
|
|
### 6. Tests Required
|
|
|
|
- Compile service/DAO/entity/util classes with `javac` when Maven is
|
|
unavailable.
|
|
- Run `PermissionPolicyCheck` or equivalent assertions for administrator,
|
|
librarian, and reader permissions.
|
|
- Run `AuthServiceCheck` or equivalent assertions for required-field failures,
|
|
invalid credentials, success, permission checks, and DAO failure fallback.
|
|
- When Maven/Tomcat dependencies are installed, run `mvn test` or
|
|
`mvn clean package` to compile Servlet and JSP integration.
|
|
|
|
### 7. Wrong vs Correct
|
|
|
|
#### Wrong
|
|
|
|
```java
|
|
// JSP, Servlet, or session code opens JDBC and stores password_hash.
|
|
```
|
|
|
|
#### Correct
|
|
|
|
```text
|
|
login.jsp -> LoginServlet -> AuthService -> UserDao -> users/roles tables
|
|
session -> AuthenticatedUser snapshot + role/permission codes only
|
|
```
|