Spring Boot’da tartibli, tushunarli, kengaytirish oson bo‘lgan backend yozish. Layered architecture, ya’ni qatlamli arxitektura. Bu mavzu ichida: Controller → Service → Repository, DTO vs Entity, mapping, @Transactional, package-by-layer va package-by-feature bor.
1. Layered Architecture nima?
Layered architecture - bu loyihani bir nechta qatlamlarga ajratib yozish usuli.
Oddiy qilib aytganda:
Client / Frontend / Mobile App
↓
Controller
↓
Service
↓
Repository
↓
DatabaseHar bir qatlamning o‘z vazifasi bor. Hammasini bitta joyga yozib yubormaymiz.
2. Nega Layered Architecture kerak?
Agar hamma kodni bitta Controller ichiga yozsak, loyiha tez buziladi.
Masalan:
@RestController
public class UserController {
@PostMapping("/users")
public User createUser(@RequestBody User user) {
// validation
// business logic
// database save
// response qaytarish
}
}Bu yomon uslub. Chunki Controller ichida hamma narsa aralashib ketadi:
HTTP request qabul qilish
ma’lumot tekshirish
biznes qoida
database bilan ishlash
response qaytarish
Kichik loyiha bo‘lsa ham ishlaydi. Lekin real loyihada bu kodni tushunish, test qilish, o‘zgartirish qiyinlashadi.
3. Asosiy qatlamlar
3.1 Controller layer
Controller - tashqi dunyo bilan aloqa qiladigan qatlam.
Frontend, mobile app yoki Postman request yuboradi. Controller shu requestni qabul qiladi.
@RestController
@RequestMapping("/api/users")
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
@PostMapping
public UserResponse create(@RequestBody UserCreateRequest request) {
return userService.create(request);
}
}Controller vazifasi:
request qabul qilish
request body olish
path variable olish
query param olish
service chaqirish
response qaytarish
Controller qilmasligi kerak:
databasega to‘g‘ridan-to‘g‘ri murojaat qilmasligi kerak
biznes logic yozmasligi kerak
murakkab hisob-kitob qilmasligi kerak
Yomon misol:
@PostMapping
public User create(@RequestBody User user) {
if (user.getAge() < 18) {
throw new RuntimeException("User must be adult");
}
return userRepository.save(user);
}Bu noto‘g‘ri. Chunki controller ichida business logic va repository ishlatilgan.
3.2 Service layer
Service - biznes logic yoziladigan joy.
Masalan:
foydalanuvchi yaratish
buyurtma hisoblash
chegirma qo‘llash
balansni tekshirish
transaction boshqarish
bir nechta repository bilan ishlash
@Service
public class UserService {
private final UserRepository userRepository;
private final UserMapper userMapper;
public UserService(UserRepository userRepository, UserMapper userMapper) {
this.userRepository = userRepository;
this.userMapper = userMapper;
}
public UserResponse create(UserCreateRequest request) {
if (request.age() < 18) {
throw new IllegalArgumentException("User must be adult");
}
User user = userMapper.toEntity(request);
User savedUser = userRepository.save(user);
return userMapper.toResponse(savedUser);
}
}Service vazifasi:
business logic
tekshiruvlar
repository chaqirish
transaction boshqarish
entity va DTO o‘rtasida ishlash
Service qilmasligi kerak:
HTTP status code bilan ko‘p ishlamasligi kerak
@RequestBody,@PathVariablekabi web annotationlarga bog‘lanmasligi kerakfrontend formatiga haddan tashqari bog‘lanmasligi kerak
3.3 Repository layer
Repository - database bilan ishlaydigan qatlam.
Spring Data JPA’da odatda interface bo‘ladi:
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
boolean existsByEmail(String email);
Optional<User> findByEmail(String email);
}Repository vazifasi:
databasega yozish
database’dan o‘qish
query bajarish
entity bilan ishlash
Repository qilmasligi kerak:
business logic yozmasligi kerak
DTO qaytarmasligi afzal
HTTP bilan aloqasi bo‘lmasligi kerak
4. Entity nima?
Entity - database jadvaliga mos keladigan Java class.
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String fullName;
private String email;
private Integer age;
// getters/setters
}Bu class database bilan bog‘langan.
Masalan jadval:
users
-----
id
full_name
email
ageEntity asosan Repository va Service qatlamida ishlatiladi.
5. DTO nima?
DTO - Data Transfer Object.
Bu client bilan ma’lumot almashish uchun ishlatiladigan class.
Masalan request DTO:
public record UserCreateRequest(
String fullName,
String email,
Integer age
) {
}Response DTO:
public record UserResponse(
Long id,
String fullName,
String email
) {
}Bu yerda age response’da qaytmayapti. Chunki clientga hamma ma’lumotni berish shart emas.
6. DTO vs Entity - nima uchun ajratamiz?
Entity’ni to‘g‘ridan-to‘g‘ri API’da ishlatish yomon
Yomon misol:
@PostMapping
public User create(@RequestBody User user) {
return userRepository.save(user);
}Nega yomon?
Chunki User entity ichida databasega oid fieldlar bor. Masalan:
private String password;
private Boolean deleted;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;Agar entity’ni response qilib qaytarsangiz, noxush holat bo‘lishi mumkin:
{
"id": 1,
"fullName": "Ali Valiyev",
"email": "ali@mail.com",
"password": "123456",
"deleted": false
}Bu xavfli.
Shuning uchun:
Request DTO → Service → Entity → Repository
Repository → Entity → Service → Response DTO7. Mapping nima?
Mapping - DTO’dan Entity yasash yoki Entity’dan DTO yasash.
Masalan manual mapping:
@Component
public class UserMapper {
public User toEntity(UserCreateRequest request) {
User user = new User();
user.setFullName(request.fullName());
user.setEmail(request.email());
user.setAge(request.age());
return user;
}
public UserResponse toResponse(User user) {
return new UserResponse(
user.getId(),
user.getFullName(),
user.getEmail()
);
}
}Bu oddiy va tushunarli usul.
Katta loyihalarda MapStruct ishlatiladi.
8. To‘liq oqim qanday ishlaydi?
Masalan frontend request yuboradi:
POST /api/users
Content-Type: application/json
{
"fullName": "Ali Valiyev",
"email": "ali@mail.com",
"age": 22
}Spring Boot’da oqim:
1. UserController requestni oladi
2. UserController UserService.create() chaqiradi
3. UserService biznes qoidani tekshiradi
4. UserService DTO’ni Entity’ga aylantiradi
5. UserRepository databasega saqlaydi
6. Service Entity’ni Response DTO’ga aylantiradi
7. Controller response qaytaradiNatija:
{
"id": 1,
"fullName": "Ali Valiyev",
"email": "ali@mail.com"
}9. @Transactional qayerga qo‘yiladi?
@Transactional odatda Service layerga qo‘yiladi.
Masalan:
@Service
public class OrderService {
private final OrderRepository orderRepository;
private final PaymentRepository paymentRepository;
public OrderService(OrderRepository orderRepository,
PaymentRepository paymentRepository) {
this.orderRepository = orderRepository;
this.paymentRepository = paymentRepository;
}
@Transactional
public void createOrder(CreateOrderRequest request) {
orderRepository.save(new Order(...));
paymentRepository.save(new Payment(...));
}
}Nega service layer?
Chunki transaction odatda bitta repository emas, butun business operation uchun kerak bo‘ladi.
Masalan:
Order save bo‘ldi
Payment save bo‘lmadiBunday holatda hammasi rollback bo‘lishi kerak. Ya’ni order ham saqlanmasligi kerak.
Shu sabab @Transactional repositoryga emas, service methodga qo‘yiladi.
10. Package-by-layer
Bu eng oddiy struktura:
src/main/java/com/example/demo
├── controller
│ └── UserController.java
├── service
│ └── UserService.java
├── repository
│ └── UserRepository.java
├── entity
│ └── User.java
├── dto
│ ├── UserCreateRequest.java
│ └── UserResponse.java
└── mapper
└── UserMapper.javaBu boshlang'ich uchun yaxshi boshlanish.
Afzalligi:
tushunish oson
Spring Boot tutoriallarda ko‘p uchraydi
kichik loyihalar uchun qulay
Kamchiligi:
loyiha kattalashsa, fayllar juda ko‘payadi
user,order,productkodlari har xil papkalarga sochilib ketadi
11. Package-by-feature
Bu real loyihalarda ko‘proq qulay bo‘ladi.
src/main/java/com/example/demo
├── user
│ ├── UserController.java
│ ├── UserService.java
│ ├── UserRepository.java
│ ├── User.java
│ ├── UserCreateRequest.java
│ ├── UserResponse.java
│ └── UserMapper.java
├── order
│ ├── OrderController.java
│ ├── OrderService.java
│ ├── OrderRepository.java
│ └── Order.java
└── product
├── ProductController.java
├── ProductService.java
├── ProductRepository.java
└── Product.javaAfzalligi:
bitta feature’ga oid kod bitta joyda turadi
katta loyihada qulay
domain bo‘yicha tartibli bo‘ladi
Java developer sifatida ikkalasini bilish kerak.
Amaliy maslahat:
Kichik o‘quv loyiha → package-by-layer
Real loyiha yoki katta loyiha → package-by-feature12. To‘liq mini misol
Entity
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String fullName;
private String email;
private Integer age;
// getters/setters
}DTO
public record UserCreateRequest(
String fullName,
String email,
Integer age
) {
}public record UserResponse(
Long id,
String fullName,
String email
) {
}Repository
public interface UserRepository extends JpaRepository<User, Long> {
boolean existsByEmail(String email);
}Mapper
@Component
public class UserMapper {
public User toEntity(UserCreateRequest request) {
User user = new User();
user.setFullName(request.fullName());
user.setEmail(request.email());
user.setAge(request.age());
return user;
}
public UserResponse toResponse(User user) {
return new UserResponse(
user.getId(),
user.getFullName(),
user.getEmail()
);
}
}Service
@Service
public class UserService {
private final UserRepository userRepository;
private final UserMapper userMapper;
public UserService(UserRepository userRepository,
UserMapper userMapper) {
this.userRepository = userRepository;
this.userMapper = userMapper;
}
@Transactional
public UserResponse create(UserCreateRequest request) {
if (userRepository.existsByEmail(request.email())) {
throw new IllegalArgumentException("Email already exists");
}
if (request.age() < 18) {
throw new IllegalArgumentException("User must be adult");
}
User user = userMapper.toEntity(request);
User savedUser = userRepository.save(user);
return userMapper.toResponse(savedUser);
}
}Controller
@RestController
@RequestMapping("/api/users")
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
@PostMapping
public UserResponse create(@RequestBody UserCreateRequest request) {
return userService.create(request);
}
}13. Eng ko‘p qilinadigan xatolar
Xato 1: Controller’dan repository chaqirish
@RestController
public class UserController {
private final UserRepository userRepository;
@PostMapping("/users")
public User create(@RequestBody User user) {
return userRepository.save(user);
}
}To‘g‘risi:
Controller → Service → RepositoryXato 2: Entity’ni response qilib qaytarish
@GetMapping("/{id}")
public User getById(@PathVariable Long id) {
return userRepository.findById(id).orElseThrow();
}To‘g‘risi:
@GetMapping("/{id}")
public UserResponse getById(@PathVariable Long id) {
return userService.getById(id);
}Xato 3: Service ichida HTTP bilan ishlash
Yomon:
public ResponseEntity<UserResponse> create(UserCreateRequest request) {
...
}Service ResponseEntity qaytarmagani yaxshi. ResponseEntity - web/controller tomonga yaqin narsa.
Yaxshiroq:
public UserResponse create(UserCreateRequest request) {
...
}14. Qisqa qoida
Esda saqlash uchun:
Controller - HTTP bilan ishlaydi
Service - biznes logic bilan ishlaydi
Repository - database bilan ishlaydi
Entity - database modeli
DTO - API modeli
Mapper - DTO va Entity o‘rtasida aylantiradi15. Javachi uchun vazifa
Bitta kichik loyiha yozing:
Product CRUD APIKerakli endpointlar:
POST /api/products
GET /api/products
GET /api/products/{id}
PUT /api/products/{id}
DELETE /api/products/{id}Struktura:
product
├── Product.java
├── ProductRepository.java
├── ProductService.java
├── ProductController.java
├── ProductCreateRequest.java
├── ProductUpdateRequest.java
├── ProductResponse.java
└── ProductMapper.javaProduct fieldlari:
id
name
price
quantityAsosiy qoida:
Controller repository’ni chaqirmasin.
Entity response sifatida qaytmasin.
Business logic service ichida bo‘lsin.Xulosa
Layered architecture - Spring Boot developer uchun eng muhim mavzulardan biri.
Bu arxitektura kodni tartibli qiladi:
Controller → Service → Repository → DatabaseDTO va Entity’ni ajratish esa xavfsizlik, tozalik va kelajakda kengaytirish uchun juda muhim.