Việc làm

06/10 · Hồ Chí Minh · Tại văn phòng

Junior/Senior Software Developers (PHP/Laravel, Java)

RiverCrane Vietnam · Backend Developer

Xem mô tả & ứng tuyển trên ITviecMô tả công việc, lương và ứng tuyển nằm ở ITviec.

10 câu hỏi có thể gặp khi phỏng vấn

Chọn theo kỹ năng và cấp của tin (Java, SQL & Database, AI / Machine Learning). Gợi ý trả lời do Drama Công Ty biên soạn để bạn ôn nhanh, không phải đề của công ty.

  1. 01Vì sao String là immutable? Khi nào dùng StringBuilder thay cho String?Java · Junior

    Gợi ý trả lời

    String bất biến: mọi thao tác "sửa" đều tạo object mới. Nhờ vậy nó an toàn khi chia sẻ giữa nhiều thread, dùng làm key cho HashMap được (hash không đổi) và JVM có thể dùng chung qua string pool.

    • Nối chuỗi trong vòng lặp bằng + tạo nhiều object trung gian, nên dùng StringBuilder:
    var sb = new StringBuilder();
    for (String s : items) sb.append(s).append(',');
    String result = sb.toString();
    
    • StringBuffer giống StringBuilder nhưng các method có synchronized, chậm hơn và hiếm khi cần.
    • Nối vài chuỗi trên một dòng thì cứ dùng +, compiler đã tối ưu sẵn.

    Người phỏng vấn muốn nghe: bạn hiểu lý do thiết kế (an toàn, hash, pool), không chỉ thuộc định nghĩa.

    Ôn thêm câu hỏi Java →
  2. 02Checked exception và unchecked exception khác nhau thế nào? try-with-resources dùng để làm gì?Java · Junior

    Gợi ý trả lời

    Checked exception (kế thừa Exception nhưng không phải RuntimeException) bị compiler bắt buộc phải catch hoặc khai báo throws, ví dụ IOException. Unchecked (RuntimeException và con của nó) thì không, ví dụ NullPointerException, IllegalArgumentException.

    • Checked hợp với lỗi bên ngoài mà caller có thể xử lý được; unchecked thường là lỗi lập trình hoặc vi phạm điều kiện.
    • try-with-resources tự gọi close() cho mọi object implement AutoCloseable, kể cả khi có exception:
    try (var reader = Files.newBufferedReader(path)) {
        return reader.readLine();
    }
    

    Hay sai: catch (Exception e) {} rồi bỏ trống, làm mất dấu lỗi. Ít nhất phải log kèm stack trace, hoặc bọc lại thành exception có ý nghĩa và ném tiếp.

    Ôn thêm câu hỏi Java →
  3. 03HashMap hoạt động bên trong như thế nào? So sánh ArrayList và LinkedList.Java · Junior

    Gợi ý trả lời

    HashMap là mảng các bucket. Khi put, nó tính hashCode() của key, suy ra chỉ số bucket, rồi lưu entry vào đó. Nhiều key trùng bucket thì nối thành danh sách; từ Java 8, khi một bucket quá dài thì chuyển thành cây đỏ đen để tránh tìm kiếm O(n).

    • Khi số phần tử vượt capacity * loadFactor (mặc định 0.75) thì map resize gấp đôi và phân bố lại.
    • get/put trung bình O(1). HashMap không thread-safe.

    ArrayList dựa trên mảng: truy cập theo index O(1), thêm cuối nhanh, chèn/xoá ở giữa phải dời phần tử. LinkedList là danh sách liên kết đôi: truy cập theo index O(n), tốn bộ nhớ hơn cho mỗi node.

    Người phỏng vấn muốn nghe: trên thực tế ArrayList gần như luôn nhanh hơn nhờ dữ liệu nằm liền nhau trong bộ nhớ (cache-friendly).

    Ôn thêm câu hỏi Java →
  4. 04Index là gì, hoạt động thế nào? Có nên đánh index cho mọi cột không?SQL & Database · Junior

    Gợi ý trả lời

    Index là cấu trúc dữ liệu phụ (thường là B-Tree) giúp tìm dòng theo giá trị cột mà không phải quét cả bảng, đổi lại tốn dung lượng và làm chậm thao tác ghi.

    • B-Tree hợp với so sánh =, <, >, BETWEEN, ORDER BY, LIKE 'abc%'.
    • Mỗi INSERT/UPDATE/DELETE phải cập nhật thêm mọi index liên quan.
    • Cột có độ chọn lọc thấp (vd. gender, is_deleted) đánh index riêng thường ít tác dụng.

    Không nên đánh index tràn lan: chỉ thêm cho cột hay xuất hiện trong WHERE, JOIN, ORDER BY của các query quan trọng, rồi kiểm tra bằng EXPLAIN.

    Hay sai: bọc cột trong hàm, vd. WHERE YEAR(created_at) = 2026 hoặc LOWER(email) = ..., khiến index thường trên cột đó không được dùng. Hãy viết lại thành khoảng thời gian hoặc dùng index trên biểu thức.

    Ôn thêm câu hỏi SQL & Database →
  5. 05Transaction là gì? Giải thích ACID.SQL & Database · Junior

    Gợi ý trả lời

    Transaction là một nhóm thao tác được thực hiện như một đơn vị: hoặc tất cả thành công (COMMIT), hoặc không có gì xảy ra (ROLLBACK).

    • Atomicity: không có trạng thái làm dở dang.
    • Consistency: sau transaction dữ liệu vẫn thoả ràng buộc (khoá ngoại, unique, check).
    • Isolation: các transaction chạy đồng thời không thấy dữ liệu dở dang của nhau, mức độ tuỳ isolation level.
    • Durability: đã commit thì không mất dù server sập (nhờ write-ahead log / redo log).
    BEGIN;
    UPDATE accounts SET balance = balance - 500 WHERE id = 1;
    UPDATE accounts SET balance = balance + 500 WHERE id = 2;
    COMMIT;
    

    Người phỏng vấn muốn nghe: một ví dụ thực tế như chuyển tiền hoặc trừ tồn kho, và bạn biết giữ transaction ngắn, không gọi API bên ngoài khi đang mở transaction.

    Ôn thêm câu hỏi SQL & Database →
  6. 06Giải thích ngắn gọn cơ chế attention và vì sao Transformer thay thế RNN trong NLP.AI / Machine Learning · Junior

    Gợi ý trả lời

    Attention cho mỗi token "nhìn" tất cả token khác và tính trọng số mức liên quan, nhờ đó nắm được phụ thuộc xa trong câu. Mỗi token tạo ra query, key, value; trọng số là softmax của tích query với key (chia cho căn bậc hai số chiều), rồi lấy tổng có trọng số của value.

    Transformer thắng RNN vì:

    • Xử lý song song cả chuỗi khi train, tận dụng GPU tốt; RNN phải đi tuần tự.
    • Ít gặp vấn đề mất thông tin ở chuỗi dài.
    • Mở rộng quy mô tốt, là nền của các LLM hiện nay.

    Đánh đổi: chi phí attention tăng theo bình phương độ dài chuỗi, nên ngữ cảnh dài tốn bộ nhớ và tính toán.

    Ôn thêm câu hỏi AI / Machine Learning →
  7. 07Dependency Injection trong Spring là gì? Vì sao nên dùng constructor injection thay cho @Autowired trên field?Java

    Gợi ý trả lời

    IoC container của Spring tạo và quản lý các bean, rồi "tiêm" phụ thuộc vào class cần dùng, thay vì class tự new. Nhờ vậy code ít phụ thuộc cứng, dễ thay implementation và dễ test.

    Constructor injection được khuyên dùng vì:

    • Field có thể là final, object luôn ở trạng thái đầy đủ sau khi tạo.
    • Test unit không cần Spring: chỉ cần new OrderService(mockRepo).
    • Constructor quá nhiều tham số là dấu hiệu class đang ôm nhiều việc.
    • Class chỉ có một constructor thì không cần ghi @Autowired.

    Nên nói thêm về scope: mặc định bean là singleton (một instance cho cả context), ngoài ra có prototype, request, session.

    Hay sai: để state thay đổi được (ví dụ biến đếm, list) trong bean singleton. Nhiều request chạy song song sẽ dùng chung và gây race condition.

    Ôn thêm câu hỏi Java →
  8. 08@Transactional hoạt động thế nào? Vì sao có lúc gắn annotation rồi mà transaction không chạy?Java

    Gợi ý trả lời

    Spring tạo proxy bao quanh bean. Khi gọi method có @Transactional qua proxy, proxy mở transaction, gọi method thật, rồi commit hoặc rollback.

    Những lý do hay gặp khiến nó "không ăn":

    • Self-invocation: method A trong cùng class gọi this.b() có @Transactional, lời gọi không đi qua proxy.
    • Method là private hoặc final: proxy không chặn được lời gọi.
    • Mặc định chỉ rollback với unchecked exception và Error. Checked exception vẫn commit, trừ khi khai báo rollbackFor = Exception.class.
    • Exception bị catch và nuốt bên trong method.

    Nên biết thêm propagation (REQUIRED, REQUIRES_NEW) và readOnly = true cho các truy vấn chỉ đọc.

    Người phỏng vấn muốn nghe: bạn giải thích được bằng cơ chế proxy, không chỉ liệt kê lỗi.

    Ôn thêm câu hỏi Java →
  9. 09Lỗi N+1 query trong JPA/Hibernate là gì và xử lý ra sao?Java

    Gợi ý trả lời

    N+1 xảy ra khi bạn lấy N bản ghi bằng 1 query, rồi mỗi lần truy cập quan hệ lazy lại phát sinh thêm 1 query. Ví dụ lấy 100 đơn hàng, rồi gọi order.getCustomer() trong vòng lặp là thành 101 query.

    Cách xử lý:

    • JOIN FETCH trong JPQL: select o from Order o join fetch o.customer.
    • @EntityGraph(attributePaths = "customer") trên method của repository.
    • @BatchSize hoặc hibernate.default_batch_fetch_size để gom lazy load thành câu IN (...).
    • Với màn hình chỉ đọc, trả thẳng DTO projection thay vì entity.

    Phát hiện bằng cách bật log SQL (spring.jpa.show-sql hoặc log của Hibernate) khi dev, hoặc dùng thống kê của Hibernate.

    Hay sai: đổi sang FetchType.EAGER cho xong. Cách này chỉ đổi chỗ lỗi và làm mọi truy vấn khác nặng hơn. Fetch join nhiều collection cùng lúc cũng dễ gây tích Descartes.

    Ôn thêm câu hỏi Java →
  10. 10Bạn có quen làm việc remote hoặc hybrid không? Làm sao để làm việc hiệu quả khi không ở văn phòng?Câu hỏi hành vi & văn hoá

    Gợi ý trả lời

    Người phỏng vấn muốn biết bạn tự quản lý được và giao tiếp chủ động khi không ngồi cạnh team.

    • Cập nhật tiến độ thường xuyên trên công cụ chung (ticket, kênh chat của team), không để người khác phải hỏi.
    • Viết rõ ràng: câu hỏi có ngữ cảnh, ghi lại kết quả thảo luận.
    • Có khung giờ làm việc ổn định, phản hồi trong giờ làm, báo trước khi vắng.
    • Dùng ngày lên văn phòng (nếu hybrid) cho thảo luận, brainstorm, gặp gỡ team.

    Câu mẫu: "Team cũ của em làm hybrid hai ngày ở văn phòng. Những ngày remote em cập nhật trạng thái task mỗi sáng và cuối ngày, vướng gì thì gọi nhanh 10 phút thay vì nhắn qua lại."

    Ôn thêm câu hỏi Câu hỏi hành vi & văn hoá →

Bạn đã phỏng vấn ở RiverCrane Vietnam?

Kể lại các vòng và câu hỏi đã gặp (ẩn danh) để người sau ôn đúng trọng tâm.

Chia sẻ kinh nghiệm phỏng vấn