// 用戶實體
public class User {
private int id;
private String username;
private String passwordHash;
private List diaries; // 關聯日記集合
// getter/setter
}
// 日記實體
public class Diary {
private int id;
private int userId; // 外鍵
private String title;
private String content;
private LocalDateTime createTime;
// getter/setter
}
public interface UserDao {
User findByUsername(String username);
void save(User user);
}
public interface DiaryDao {
void save(Diary diary);
List findByUserId(int userId);
Diary findById(int id);
void update(Diary diary);
void delete(int id);
}
public class UserService {
private UserDao userDao;
private DiaryDao diaryDao;
private User currentUser; // 當前登錄用戶(線程局部或 Session)
// 註冊
public boolean register(String username, String password) {
if (userDao.findByUsername(username) != null) return false;
User user = new User();
user.setUsername(username);
user.setPasswordHash(hash(password));
userDao.save(user);
return true;
}
// 登錄
public boolean login(String username, String password) {
User user = userDao.findByUsername(username);
if (user != null && verify(password, user.getPasswordHash())) {
this.currentUser = user; // 記錄登錄狀態
return true;
}
return false;
}
// 寫日記(核心:關聯當前用戶)
public void writeDiary(String title, String content) {
if (currentUser == null) throw new IllegalStateException("請先登錄");
Diary diary = new Diary();
diary.setUserId(currentUser.getId());
diary.setTitle(title);
diary.setContent(content);
diary.setCreateTime(LocalDateTime.now());
diaryDao.save(diary);
}
// 獲取當前用戶日記列表
public List getMyDiaries() {
if (currentUser == null) return Collections.emptyList();
return diaryDao.findByUserId(currentUser.getId());
}
}
| 問題 | 決策 | 理由 |
|---|---|---|
| 日記集合放在哪? | User 實體中持有 List | 避免加載用戶時一次性查出所有日記(OOM 風險),DAO 按需分頁查詢 |
| 操作類單例嗎? | 非單例,Web 環境下每請求一個實例(或 Spring @Service 單例但無狀態) | currentUser 應存放在 Session/ThreadLocal,而非 Service 實例字段 |
| 如何體現「一用戶多日記」? | Diary 表有 user_id 外鍵,DAO 查詢 WHERE user_id = ? | 關係型數據庫標準一對多建模,內存中通過 userId 關聯 |
@Service
public class UserService {
@Autowired UserRepository userRepo;
@Autowired DiaryRepository diaryRepo;
@Transactional
public Diary writeDiary(String title, String content) {
User user = getCurrentUser(); // 從 SecurityContext/Session 獲取
Diary diary = new Diary();
diary.setUser(user); // JPA 自動維護外鍵
diary.setTitle(title);
diary.setContent(content);
return diaryRepo.save(diary);
}
}
核心原則:實體類映射數據庫關係,DAO 封裝 SQL,Service 協調業務流程並持有當前用戶上下文。日記集合不作為 User 字段長駐內存,而是通過 userId 動態查詢。