[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"question-sovremennaya-razrabotka-web-kak-organizovat-rabotu-s-dannymi-v-spring-boot":3},{"id":4,"slug":5,"topicId":6,"topicSlug":7,"topicName":8,"topicEmoji":9,"question":10,"answer":11,"codeLang":12,"codeSrc":12,"important":12,"commonMistakes":12,"modernUsage":12,"difficulty":13,"tags":14,"related":20,"progress":21,"seo":22},1190,"kak-organizovat-rabotu-s-dannymi-v-spring-boot",37,"sovremennaya-razrabotka-web","Современная разработка WEB","🌐","Как организовать работу с данными в Spring Boot?","Spring Data JPA с Hibernate 6 остаётся основным способом работы с реляционными данными. PostgreSQL занимает позицию дефолтной базы данных для Java-проектов.\n\n### JPA-сущность\n\n\u003Cdetails>\n\u003Csummary>Пример JPA-сущности с optimistic locking\u003C\u002Fsummary>\n\n```java\n@Entity\n@Table(name = \"orders\")\npublic class OrderJpaEntity {\n\n    @Id\n    @GeneratedValue(strategy = GenerationType.UUID)\n    private UUID id;\n\n    @Column(nullable = false)\n    private UUID customerId;\n\n    @Enumerated(EnumType.STRING)\n    @Column(nullable = false)\n    private OrderStatus status;\n\n    @OneToMany(mappedBy = \"order\", cascade = CascadeType.ALL, orphanRemoval = true)\n    private List\u003COrderItemJpaEntity> items = new ArrayList\u003C>();\n\n    @Column(nullable = false, precision = 19, scale = 2)\n    private BigDecimal totalAmount;\n\n    @CreationTimestamp\n    @Column(updatable = false)\n    private Instant createdAt;\n\n    @UpdateTimestamp\n    private Instant updatedAt;\n\n    @Version\n    private Long version; \u002F\u002F Optimistic locking\n\n    public void addItem(OrderItemJpaEntity item) {\n        items.add(item);\n        item.setOrder(this);\n        recalculateTotal();\n    }\n}\n```\n\n\u003C\u002Fdetails>\n\n### Репозиторий с различными типами запросов\n\n\u003Cdetails>\n\u003Csummary>Пример репозитория\u003C\u002Fsummary>\n\n```java\npublic interface OrderJpaRepository extends JpaRepository\u003COrderJpaEntity, UUID> {\n\n    \u002F\u002F Derived query\n    List\u003COrderJpaEntity> findByCustomerIdAndStatus(UUID customerId, OrderStatus status);\n\n    \u002F\u002F JPQL с проекцией\n    @Query(\"\"\"\n        SELECT new com.example.order.adapter.out.persistence.OrderSummary(\n            o.id, o.status, o.totalAmount, o.createdAt\n        )\n        FROM OrderJpaEntity o\n        WHERE o.customerId = :customerId\n        ORDER BY o.createdAt DESC\n        \"\"\")\n    Page\u003COrderSummary> findOrderSummaries(\n        @Param(\"customerId\") UUID customerId, Pageable pageable);\n\n    \u002F\u002F Native query\n    @Query(value = \"\"\"\n        SELECT o.* FROM orders o\n        WHERE o.status = 'CREATED'\n        AND o.created_at \u003C NOW() - INTERVAL '30 minutes'\n        FOR UPDATE SKIP LOCKED\n        LIMIT :limit\n        \"\"\", nativeQuery = true)\n    List\u003COrderJpaEntity> findStaleOrders(@Param(\"limit\") int limit);\n\n    \u002F\u002F Batch update\n    @Modifying\n    @Query(\"UPDATE OrderJpaEntity o SET o.status = :status WHERE o.id IN :ids\")\n    int updateStatusBatch(@Param(\"ids\") List\u003CUUID> ids, @Param(\"status\") OrderStatus status);\n}\n```\n\n\u003C\u002Fdetails>\n\n### Настройка Hibernate для production\n\n```yaml\nspring:\n  jpa:\n    open-in-view: false  # Отключить ОБЯЗАТЕЛЬНО\n    hibernate:\n      ddl-auto: validate  # Только валидация, миграции через Flyway\n    properties:\n      hibernate:\n        default_batch_fetch_size: 20\n        jdbc:\n          batch_size: 50\n        order_inserts: true\n        order_updates: true\n```\n\n### Redis для кэширования\n\n```java\n@Service\npublic class ProductService {\n\n    @Cacheable(value = \"products\", key = \"#productId\")\n    public Product getProduct(UUID productId) {\n        return productRepository.findById(productId)\n            .orElseThrow(() -> new ProductNotFoundException(productId));\n    }\n\n    @CacheEvict(value = \"products\", key = \"#product.id\")\n    public Product updateProduct(Product product) {\n        return productRepository.save(product);\n    }\n}\n```\n\n### Частые ошибки\n\n- N+1 проблема: загрузка связанных сущностей в цикле. Решение: @EntityGraph, JOIN FETCH, default_batch_fetch_size\n- Использование ddl-auto=update в production — потенциальная потеря данных\n- Кэширование без стратегии инвалидации\n- Игнорирование connection pool настроек — дефолтный HikariCP pool size (10) может быть недостаточен\n- open-in-view=true (значение по умолчанию) — держит транзакцию открытой на весь HTTP-запрос\n\n> **На собеседовании:** три обязательных пункта: 1) open-in-view=false, 2) ddl-auto=validate в production, 3) знание N+1 проблемы и способов решения. Без этих знаний разговор о JPA на middle-уровне не пройдёт. Бонус: упомянуть, что Virtual Threads снизили необходимость в R2DBC.","","middle",[15,16,17,18,19],"postgresql","spring-data","spring-boot","jpa","hibernate",[],null,{"title":23,"description":24,"ogTitle":25,"ogDescription":26,"keywords":27,"schemaAnswer":38,"featuredSnippetReady":39},"Как организовать работу с данными в Spring Boot — Gymterview","Spring Data JPA с Hibernate 6: JPA-сущности, репозитории, optimistic locking, настройка для production. N+1 проблема, open-in-view, Redis-кэширование.","Работа с данными в Spring Boot: JPA, Hibernate 6, PostgreSQL — Gymterview","Spring Data JPA + Hibernate 6 + PostgreSQL: сущности, репозитории, N+1 проблема, production-настройки и Redis-кэширование.",[28,29,30,31,32,33,34,35,36,37],"Spring Data JPA","Hibernate 6","PostgreSQL","N+1 проблема","open-in-view","optimistic locking","HikariCP","Redis кэш","Spring Boot","собеседование","Spring Data JPA с Hibernate 6 — основной способ работы с реляционными данными. PostgreSQL — дефолтная БД. Обязательные настройки для production: open-in-view=false, ddl-auto=validate, default_batch_fetch_size для борьбы с N+1. Оптимистичная блокировка через @Version. Redis для кэширования через @Cacheable. Virtual Threads снизили необходимость в R2DBC.",true]