← 개발일지

Java DAO vs DTO: Roles, Rules, and Naming


Java DAO vs DTO: Roles, Rules, and Naming

If you've ever gotten a code review comment like "DAO is being used like a DTO — please separate the roles" and stared at it blankly, you're not alone.

Both DAO and DTO deal with data. Both live somewhere in your package structure. So what's actually the difference, and why does it matter?

Let's clear it up — roles, naming conventions, and all.


What Is a DAO?

A DAO (Data Access Object) is responsible for talking to the database. SQL queries, connection management, result mapping — that's all DAO territory.

// ✅ Correct DAO usage
public class UserDao {
    public UserDto findById(int id) {
        // Database SELECT logic
        String sql = "SELECT * FROM users WHERE id = ?";
        // Handle Connection, PreparedStatement...
        return userDto;
    }

    public void save(UserDto dto) {
        // Database INSERT logic
        String sql = "INSERT INTO users (name, email) VALUES (?, ?)";
        // ...
    }
}

Think of it as the gatekeeper between your application and the database.


What Is a DTO?

A DTO (Data Transfer Object) is a plain container for data. It moves information between layers — Controller, Service, DAO — without carrying any business logic.

// ✅ Correct DTO usage
public class UserDto {
    private String name;
    private String email;

    public String getName() { return name; }
    public void setName(String name) { this.name = name; }

    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
}

Fields and getters/setters only. No SQL. No logic. Just data.


Quick Comparison

| | DAO | DTO | |---|---|---| | Purpose | Database access | Data transfer between layers | | Contains | SQL, connection logic | Fields, getters, setters | | Example | UserDao.java | UserDto.java |


The Common Mistake: DAO That Acts Like a DTO

Here's an anti-pattern that comes up more often than you'd think:

// ❌ Anti-pattern: named DAO, behaves like a DTO
public class UserDAO {
    private String name;
    private String email;

    public String getName() { return name; }
    public String getEmail() { return email; }

    // No database access logic anywhere!
}

The class is called UserDAO, but there's no SQL, no connection — just fields. Anyone who opens this file expecting database logic will be confused. The fix is simple: if a class only holds data, it belongs in the dto package as a proper DTO.


Package Naming: Why dao, Not DAO?

Java's official style guide says: package names are all lowercase. No exceptions, even for acronyms.

✅ com.project.dao
✅ com.project.dto
✅ com.project.service

❌ com.project.DAO
❌ com.project.DTO

The reason is practical: some file systems (like Windows) aren't case-sensitive, so uppercase package names can cause conflicts. Lowercase keeps things unambiguous across platforms.


Class Naming: AlramTalkBasDTOAlramTalkBasDto

Class names use PascalCase — capitalize the first letter of each word. When your class name contains an acronym like DTO or DAO, treat it as a single word: capitalize only the first letter.

// ❌ Before
public class AlramTalkBasDTO { }

// ✅ After
public class AlramTalkBasDto { }

The same rule applies to other common acronyms:

| Acronym | PascalCase | |---------|-----------| | DTO | Dto | | DAO | Dao | | HTTP | Http | | URL | Url | | ID | Id |

Note: Some teams keep acronyms fully uppercase (e.g., UserDTO). Team conventions always win — the key is consistency within your codebase.


Your Refactoring Checklist

Got this kind of feedback from a code review? Here's exactly what to do:

  • [ ] Rename package DAOdao and DTOdto (all lowercase)
  • [ ] Check each class in dao — does it actually contain database logic?
  • [ ] If a class only holds fields and getters, move it to dto and refactor accordingly
  • [ ] Update class names: UserDAOUserDao, UserDTOUserDto
  • [ ] Verify no broken imports after renaming

IntelliJ tip: Use Shift+F6 (Rename) or right-click → Refactor → Rename. It automatically updates all import paths — a huge time-saver.


Naming conventions can feel like nitpicking, but they pay off fast. When every class name tells you exactly what it does, you spend less time guessing and more time building.