рд╕реНрдкреНрд░рд┐рдВрдЧ рдбреЗрдЯрд╛ рдЬреЗрдкреАрдП: рдлрд╛рдЗрд▓реЗрдВ рд▓рд╛рдирд╛

рдЕрднрд┐рд╡рд╛рджрди, рдпрд╣ рд╕реНрдкреНрд░рд┐рдВрдЧ рдбреЗрдЯрд╛ рдЬреЗрдкреАрдП рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рджреВрд╕рд░реА рдкреЛрд╕реНрдЯ рд╣реИред рдкрд╣рд▓рд╛ рднрд╛рдЧ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдкрд╛рдиреА рдХреЗ рдиреАрдЪреЗ рдХреА рд░реЗрдХ рдХреЗ рд▓рд┐рдП рд╕рдорд░реНрдкрд┐рдд рдерд╛, рд╕рд╛рде рд╣реА рд╕рд╛рде рдЕрдиреБрднрд╡реА рд▓реЛрдЧреЛрдВ рдХреЗ рд╕реБрдЭрд╛рд╡ рднреАред рдЗрд╕ рднрд╛рдЧ рдореЗрдВ рд╣рдо рдмрд╛рдд рдХрд░реЗрдВрдЧреЗ рдХрд┐ рдЕрдкрдиреА рдЖрд╡рд╢реНрдпрдХрддрд╛рдУрдВ рдХреЗ рд▓рд┐рдП рд░реВрдкрд░реЗрдЦрд╛ рдХреЛ рдХреИрд╕реЗ рддреЗрдЬ рдХрд┐рдпрд╛ рдЬрд╛рдПред рд╡рд░реНрдгрд┐рдд рд╕рднреА рдЙрджрд╛рд╣рд░рдг рдпрд╣рд╛рдВ рдЙрдкрд▓рдмреНрдз рд╣реИрдВ ред


рдЧрд┐рдирддрд╛


рдЪрд▓реЛ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ, рд╢рд╛рдпрдж, рдПрдХ рд╕рд░рд▓ рдФрд░ рдПрдХ рд╣реА рд╕рдордп рдореЗрдВ рд╕рд╛рдорд╛рдиреНрдп рдХрд╛рд░реНрдп рдХреЗ рд╕рд╛рде: рдПрдХ рдЗрдХрд╛рдИ рдХреЛ рд▓реЛрдб рдХрд░рддреЗ рд╕рдордп, рдЪреБрдирд┐рдВрджрд╛ рд░реВрдк рд╕реЗ рдЗрд╕рдХреА "рдмреЗрдЯреА" рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИред рдПрдХ рд╕рд╛рдзрд╛рд░рдг рдЙрджрд╛рд╣рд░рдг рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ:


@Entity public class Child { @Id private Long id; @JoinColumn(name = "parent_id") @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) private Parent parent; } @Entity public class Parent { @Id private Long id; } 

рд╣рдорд╛рд░реЗ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ рдмрд╛рд▓ рдЗрдХрд╛рдИ рдЖрд▓рд╕реА рд╣реИ: рд╣рдо Child рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╕рдордп рдЕрдирд╛рд╡рд╢реНрдпрдХ рдбреЗрдЯрд╛ рд▓реЛрдб рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ (рдФрд░ рдПрд╕рдХреНрдпреВрдПрд▓ рдХреНрд╡реЗрд░реА рдореЗрдВ рджреВрд╕рд░реА рддрд╛рд▓рд┐рдХрд╛ рдореЗрдВ рд╢рд╛рдорд┐рд▓ рд╣реЛрдВ)ред рд▓реЗрдХрд┐рди рд╣рдорд╛рд░реЗ рдЖрд╡реЗрджрди рдореЗрдВ рдХреБрдЫ рдорд╛рдорд▓реЛрдВ рдореЗрдВ рд╣рдо рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рд╣рдореЗрдВ рдмрдЪреНрдЪреЗ рдФрд░ рдЙрд╕рдХреЗ рдорд╛рддрд╛-рдкрд┐рддрд╛ рджреЛрдиреЛрдВ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреАред рдпрджрд┐ рдЖрдк рдЗрдХрд╛рдИ рдХреЛ рдЖрд▓рд╕реА рдЫреЛрдбрд╝ рджреЗрддреЗ рд╣реИрдВ, рддреЛ рд╣рдореЗрдВ 2 рдЕрд▓рдЧ-рдЕрд▓рдЧ рдЕрдиреБрд░реЛрдз рдорд┐рд▓рддреЗ рд╣реИрдВред рдпрджрд┐ рдЖрдк FetchType.LAZY рдХреЛ рд╣рдЯрд╛рдХрд░ рддреЗрдЬреА рд╕реЗ рд▓реЛрдбрд┐рдВрдЧ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рджреЛрдиреЛрдВ рд╕рдВрд╕реНрдерд╛рдПрдВ рд╣рдореЗрд╢рд╛ рдкрд╣рд▓реЗ рдЕрдиреБрд░реЛрдз рдкрд░ рд▓реЛрдб рдХреА рдЬрд╛рдПрдВрдЧреА (рдФрд░ рд╣рдо рдРрд╕рд╛ рдирд╣реАрдВ рдЪрд╛рд╣рддреЗ рд╣реИрдВ)ред


JPQL рдмреЙрдХреНрд╕ рд╕реЗ рдПрдХ рдЕрдЪреНрдЫрд╛ рд╕рдорд╛рдзрд╛рди рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ - рдпрд╣ fetch рдХреАрд╡рд░реНрдб рд╣реИ:


 public interface ChildRepository extends JpaRepository<Child, Long> { @Query("select c from Child c join fetch c.parent where c.id = :id") Child findByIdFetchParent(@Param("id") Long id); } 

рдпрд╣ рдЕрдиреБрд░реЛрдз рд╕рд░рд▓ рдФрд░ рд╕реНрдкрд╖реНрдЯ рд╣реИ, рд▓реЗрдХрд┐рди рдЗрд╕рдореЗрдВ рдХрдорд┐рдпрд╛рдВ рд╣реИрдВ:


  • рд╣рдордиреЗ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ JpaRepository::findById рдХреЗ рддрд░реНрдХ рдХреЛ JpaRepository::findById рдХреЛ рд╕реНрдкрд╖реНрдЯ рд▓реЛрдбрд┐рдВрдЧ рдЬреЛрдбрд╝рдХрд░
  • @Query рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╡рд░реНрдгрд┐рдд рдкреНрд░рддреНрдпреЗрдХ рдХреНрд╡реЗрд░реА рдХреЛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╕реНрдЯрд╛рд░реНрдЯрдЕрдк рдкрд░ @Query рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рдХреНрд╡реЗрд░реА рдХреЛ рдкрд╛рд░реНрд╕ рдХрд░рдиреЗ, рддрд░реНрдХреЛрдВ рдХреЛ рдЬрд╛рдВрдЪрдиреЗ, рдЖрджрд┐ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ (рджреЗрдЦреЗрдВ org.springframework.data.jpa.repository.query.SimpleJpaQuery :: validateQuery )ред рдпрд╣ рд╕рдм рдХрд╛рдо рд╣реИ рдЬреЛ рд╕рдордп рдФрд░ рд╕реНрдореГрддрд┐ рд▓реЗрддрд╛ рд╣реИред
  • рджрд░реНрдЬрдиреЛрдВ рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдФрд░ entwined рд╕рдВрд╕реНрдерд╛рдУрдВ рдХреЗ рд╕рд╛рде рдПрдХ рдмрдбрд╝реА рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ рдЗрд╕ рддрд░рд╣ рдХреЗ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХрд╛ рдЙрдкрдпреЛрдЧ (рдХрднреА-рдХрднреА рдПрдХ рджрд░реНрдЬрди "рдмреЗрдЯрд┐рдпреЛрдВ") рдХреЗ рд╕рд╛рде рдПрдХ рджрд╣рдирд╢реАрд▓ рд╡рд┐рд╕реНрдлреЛрдЯ рдХрд╛ рдХрд╛рд░рдг рд╣реЛрдЧрд╛ред

рдорд╛рдпрдиреЗ рд░рдЦрддрд╛ рд╣реИ рд╣рдорд╛рд░реА рд╕рд╣рд╛рдпрддрд╛ рдХреЗ рд▓рд┐рдП:


 @Entity @NamedEntityGraphs(value = { @NamedEntityGraph( name = Child.PARENT, attributeNodes = @NamedAttributeNode("parent") ) }) public class Child { public static final String PARENT = "Child[parent]"; @Id private Long id; @JoinColumn(name = "parent_id") @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) private Parent parent; } 

рдЧреНрд░рд╛рдл рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдирд╛ рдЖрд╕рд╛рди рд╣реИ, рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╕рдордп рдХрдард┐рдирд╛рдЗрдпрд╛рдВ рд╢реБрд░реВ рд╣реЛрддреА рд╣реИрдВред рдЕрдкрдиреЗ рдкреЗрдЬ рдкрд░ рд╕реНрдкреНрд░рд┐рдВрдЧ рдбрд╛рдЯрд╛ рдЬреЗрдкреАрдП рдЗрд╕реЗ рдЗрд╕ рддрд░рд╣ рд╕реЗ рдХрд░рдиреЗ рдХрд╛ рд╕реБрдЭрд╛рд╡ рджреЗрддрд╛ рд╣реИ (рдЬреИрд╕рд╛ рдХрд┐ рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдкрд░ рд▓рд╛рдЧреВ рд╣реЛрддрд╛ рд╣реИ)


 public interface GroupRepository extends JpaRepository<GroupInfo, String> { @EntityGraph(value = Child.PARENT) @Query("select c from Child c where c.id = :id") Child findByIdFetchParent(@Param("id") Long id); } 

рдпрд╣рд╛рдВ рд╣рдо рд╕рднреА рд╕рдорд╛рди рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЛ рджреЗрдЦрддреЗ рд╣реИрдВ (рд╕рд┐рд╡рд╛рдп рдЗрд╕рдХреЗ рдХрд┐ рд▓рд┐рдЦрд┐рдд рдЕрдиреБрд░реЛрдз рдереЛрдбрд╝рд╛ рдЖрд╕рд╛рди рд╣реЛ рдЧрдпрд╛ рд╣реИ)ред рдЖрдк рдЙрдиреНрд╣реЗрдВ рдареАрдХ рдЯреНрдпреВрдирд┐рдВрдЧ рдХреА рдорджрдж рд╕реЗ рдПрдХ рдЭрдЯрдХреЗ рдореЗрдВ рд╕рдорд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЕрдкрдирд╛ рд╕реНрд╡рдпрдВ рдХрд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдмрдирд╛рдПрдБ, рдЬрд┐рд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рд╣рдо рдмреЙрдХреНрд╕рд┐рдВрдЧ JpaRepository рдмрдЬрд╛рдп рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП JpaRepository :


 @NoRepositoryBean public interface BaseJpaRepository<T, ID extends Serializable> extends JpaRepository<T, ID> { T findById(ID id, String graphName); } 

рдЕрдм рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди:


 public class BaseJpaRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID> implements BaseJpaRepository<T, ID> { private final JpaEntityInformation<T, ?> entityInfo; private final EntityManager entityManager; public BaseJpaRepositoryImpl(JpaEntityInformation<T, ?> ei, EntityManager em) { super(ei, em); this.entityInfo = ei; this.entityManager = em; } @Override public T findById(ID id, String graphName) { Assert.notNull(id, "The given id must not be null!"); //  EntityGraph<?> graph = entityManager.getEntityGraph(graphName); Map<String, Object> hints = singletonMap(QueryHints.HINT_LOADGRAPH, graph); return entityManager.find(getDomainClass(), id, hints); } 

рдЕрдм рд╕реНрдкреНрд░рд┐рдВрдЧ рдХреЛ рд╣рдорд╛рд░реЗ рдЖрд╡реЗрджрди рдХреЗ рд╕рднреА рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдХреЗ рдЖрдзрд╛рд░ рдХреЗ рд░реВрдк рдореЗрдВ BaseJpaRepositoryImpl рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП BaseJpaRepositoryImpl рдХрд░реЗрдВ:


 @EnableJpaRepositories(repositoryBaseClass = BaseJpaRepositoryImpl.class) public class AppConfig { } 

рдЕрдм рд╣рдорд╛рд░реА рд╡рд┐рдзрд┐ рд╣рдорд╛рд░реЗ BaseJpaRepository рд╕реЗ рд╡рд┐рд░рд╛рд╕рдд рдореЗрдВ рдорд┐рд▓реА рд╕рднреА рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рд╕реЗ рдЙрдкрд▓рдмреНрдз рд╣реЛрдЧреАред


рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдореЗрдВ рдПрдХ рджреЛрд╖ рд╣реИ рдЬреЛ рдмрд╣реБрдд рдореЛрдЯрд╛ рд╕реБрдЕрд░ рдбрд╛рд▓ рд╕рдХрддрд╛ рд╣реИред


рдЕрдкрдиреЗ рд▓рд┐рдП рд╕реЛрдЪрдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реЗрдВ

рд╕рдорд╕реНрдпрд╛ рдпрд╣ рд╣реИ рдХрд┐ рд╣рд╛рдЗрдмрд░рдиреЗрдЯ (рд▓реЗрдЦрди рдХреЗ рд╕рдордп рдХрдо рд╕реЗ рдХрдо) рд░реЗрдЦрд╛рдВрдХрди рдФрд░ рд░реЗрдЦрд╛рдВрдХрди рдХреЗ рдирд╛рдореЛрдВ рд╕реЗ рдореЗрд▓ рдирд╣реАрдВ рдЦрд╛рддрд╛ рд╣реИред рдЗрд╕рдХреЗ рдХрд╛рд░рдг, рдЬрдм рд╣рдо рдХрд┐рд╕реА рдЪреАрдЬрд╝ рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рддреЗ рд╣реИрдВ рддреЛ рд░рдирдЯрд╛рдЗрдо рддреНрд░реБрдЯрд┐ рд╣реЛ рд╕рдХрддреА рд╣реИ


 Optional<MyEntity> entity = repository.findById(id, NON_EXISTING_GRAPH); 

рдЖрдк рдкрд░реАрдХреНрд╖рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдорд╛рдзрд╛рди рдХреЗ рд╕реНрд╡рд╛рд╕реНрдереНрдп рдХреА рдЬрд╛рдВрдЪ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:


 @Sql("/ChildRepositoryGraphTest.sql") public class ChildRepositoryGraphTest extends TestBase { private final Long childId = 1L; @Test public void testGraph_expectFieldInitialized() { Child child1 = childRepository.findOne(childId, Child.PARENT); boolean initialized = Hibernate.isInitialized(child1.getParent()); assertTrue(initialized); } @Test public void testGraph_expectFieldNotInitialized() { Child child1 = childRepository .findById(childId) .orElseThrow(NullPointerException::new); boolean initialized = Hibernate.isInitialized(child1.getParent()); assertFalse(initialized); } } 

рдЬрдм рдкреЗрдбрд╝ рдмрдбрд╝реЗ рдереЗ


рдФрд░ рд╣рдо рдЫреЛрдЯреЗ рдФрд░ рдЕрдиреБрднрд╡рд╣реАрди рдереЗ, рд╣рдореЗрдВ рдЕрдХреНрд╕рд░ рдпрд╣ рдХреЛрдб рджреЗрдЦрдирд╛ рдкрдбрд╝рддрд╛ рдерд╛:


 public List<DailyRecord> findBetweenDates(Date from, Date to) { StringBuilder query = new StringBuilder("from Record "); if (from != null) { query.append(" where date >=").append(format(from)).append(" "); } if (to != null) { if (from == null) { query.append(" where date <= " + format(to) + " "); } else { query.append(" and date <= " + format(to) + " "); } } return em.createQuery(query.toString(), DailyRecord.class).getResultList(); } 

рдпрд╣ рдХреЛрдб рдЯреБрдХрдбрд╝рд╛ рджреНрд╡рд╛рд░рд╛ рдЕрдиреБрд░реЛрдз рдЯреБрдХрдбрд╝рд╛ рдПрдХрддреНрд░ рдХрд░рддрд╛ рд╣реИред рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЗ рдиреБрдХрд╕рд╛рди рд╕реНрдкрд╖реНрдЯ рд╣реИрдВ:


  • рдЖрдкрдХреЛ рдЕрдкрдиреЗ рд╣рд╛рдереЛрдВ рд╕реЗ рдмрд╣реБрдд рдХреБрдЫ рдХрд░рдирд╛ рд╣реИ
  • рдЬрд╣рд╛рдБ рдореИрдиреБрдЕрд▓ рдХрд╛рдо рд╣реИ - рдЧрд▓рддрд┐рдпрд╛рдБ рд╣реИрдВ
  • рдХреЛрдИ рд╕рд┐рдВрдЯреИрдХреНрд╕ рд╣рд╛рдЗрд▓рд╛рдЗрдЯрд┐рдВрдЧ (рд░рдирдЯрд╛рдЗрдо рдХреЗ рджреМрд░рд╛рди рдЯрд╛рдЗрдкреЛ рдкреЙрдк рдЕрдк)
  • рдХреЛрдб рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдХрд░рдирд╛ рдФрд░ рдЙрд╕реЗ рдмрдирд╛рдП рд░рдЦрдирд╛ рдмрд╣реБрдд рдореБрд╢реНрдХрд┐рд▓ рд╣реИ

рдереЛрдбрд╝реА рджреЗрд░ рдмрд╛рдж, рдорд╛рдирджрдВрдб рдПрдкреАрдЖрдИ рджрд┐рдЦрд╛рдИ рджрд┐рдпрд╛, рдЬрд┐рд╕рдиреЗ рд╣рдореЗрдВ рдЙрдкрд░реЛрдХреНрдд рдХреЛрдб рдХреЛ рдереЛрдбрд╝рд╛ рдирд┐рдЪреЛрдбрд╝рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреА:


 public List<DailyRecord> findBetweenDates(Date from, Date to) { Criteria criteria = em .unwrap(Session.class) .createCriteria(DailyRecord.class); if (from != null) { criteria.add(Expression.ge("date", from)); } if (to != null) { criteria.add(Expression.le("date", to)); } return criteria.list(); } 

рдорд╛рдирджрдВрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рдХрдИ рдлрд╛рдпрджреЗ рд╣реИрдВ:


  • "рддрд┐рдерд┐" рдЬреИрд╕реЗ "рд╡рд╛рдпрд░реНрдб" рдореВрд▓реНрдпреЛрдВ рдХреЗ рдмрдЬрд╛рдп рдПрдХ рдореЗрдЯрд╛рдореЙрдбрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛
  • рдЕрдиреБрд░реЛрдз рдХреЗ рдирд┐рд░реНрдорд╛рдг рдореЗрдВ рдХреБрдЫ рддреНрд░реБрдЯрд┐рдпрд╛рдВ рд╕рдВрдХрд▓рди рддреНрд░реБрдЯрд┐рдпрд╛рдВ рд╣реИрдВ, рдЕрд░реНрдерд╛рддреН, рд▓рд┐рдЦрддреЗ рд╕рдордп рдЙрдиреНрд╣реЗрдВ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдкрддрд╛ рдЪрд▓ рдЬрд╛рддрд╛ рд╣реИ
  • рдХреЛрдб рдмреЗрд╡рдХреВрдл рдЪрд┐рдкрдХрд╛рдиреЗ рд╡рд╛рд▓реЗ рддрд╛рд░ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдЫреЛрдЯрд╛ рдФрд░ рдЕрдзрд┐рдХ рд╕рдордЭрджрд╛рд░ рд╣реИ

рдЗрд╕рдХреЗ рдиреБрдХрд╕рд╛рди рднреА рд╣реИрдВ:


  • рдХреЛрдб рд╕рдордЭрдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рдЬрдЯрд┐рд▓ рд╣реИ
  • рдЗрд╕ рддрд░рд╣ рдХреЗ рдкреНрд░рд╢реНрдиреЛрдВ рдХреЛ рд▓рд┐рдЦрдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдкрдХреЛ рдЕрдкрдирд╛ рд╣рд╛рде рднрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ (рдореБрдЭреЗ рдпрд╛рдж рд╣реИ рдХрд┐ рдЬрдм рдореБрдЭреЗ рдкрд╣рд▓реА рдмрд╛рд░ рдЗрд╕ рддрд░рд╣ рдХреЗ рдкреНрд░рд╢реНрдиреЛрдВ рдореЗрдВ рддреНрд░реБрдЯрд┐ рд╕реБрдзрд╛рд░ рд╕реЗ рдирд┐рдкрдЯрдирд╛ рдкрдбрд╝рд╛ рдерд╛, рддреЛ рдХрднреА-рдХрднреА 100-150 рд▓рд╛рдЗрдиреЛрдВ рд╕реЗ рдпреБрдХреНрдд рд╣реЛрддрд╛ рд╣реИ, рдмреНрд░рд╛рдВрдЪрд┐рдВрдЧ рдХреЗ рд╕рд╛рде, рдЖрджрд┐)
  • рдПрдХ рдЬрдЯрд┐рд▓ рдХреНрд╡реЗрд░реА рдмрд▓реНрдХрд┐ рдмреЛрдЭрд┐рд▓ рд╣реИ (50 рд▓рд╛рдЗрдиреЗрдВ рд╕реАрдорд╛ рд╕реЗ рдмрд╣реБрдд рджреВрд░ рд╣реИрдВ)

рдореИрдВ рдЗрд╕реЗ рдЖрд╕рд╛рдиреА рд╕реЗ рдФрд░ рдЖрдирдВрдж рдХреЗ рд╕рд╛рде рд╡рд┐рдХрд╕рд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ, рдЗрд╕рд▓рд┐рдП рдореИрдВ рдЗрди рджреЛрдиреЛрдВ рддрд░реАрдХреЛрдВ рдХреА рддрд░рд╣ рдирд╣реАрдВ рд╣реВрдВред


рдЖрдЗрдП рд╣рдо рдЕрдкрдиреЗ рджреНрд╡рд╛рд░рд╛ рдкрд╣рд▓реЗ рд╕реЗ рдЬрд╛рдБрдЪреА рдЧрдИ рдЗрдХрд╛рдИ рдХреЛ рджреЗрдЦреЗрдВ:


 @Entity public class Child { @Id private Long id; @JoinColumn(name = "parent_id") @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) private Parent parent; //... @OneToMany(mappedBy = "owner", cascade = CascadeType.ALL) @LazyCollection(value = LazyCollectionOption.EXTRA) private List<Toy> toys = new ArrayList<>(); } 

рдореИрдВ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдореЛрдб (рдФрд░ рдЙрдирдХреЗ рд╕рдВрдпреЛрдЬрди) рдореЗрдВ рдПрдХ рдЗрдХрд╛рдИ рдХреЛ рд▓реЛрдб рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдирд╛ рдЪрд╛рд╣реВрдВрдЧрд╛:


  • рд▓реЛрдб (рдпрд╛ рдирд╣реАрдВ) рдЬрдирдХ
  • рд▓реЛрдб (рдпрд╛ рдирд╣реАрдВ) рдЦрд┐рд▓реМрдиреЗ
  • рдмрдЪреНрдЪреЛрдВ рдХреЛ рдЙрдореНрд░ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдХреНрд░рдордмрджреНрдз рдХрд░реЗрдВ

рдпрджрд┐ рдЖрдк рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рддреЗ рд╣реИрдВ, рдЕрд░реНрдерд╛рддреН, рдмрд╣реБрдд рд╕рд╛рд░реЗ рдкреНрд░рд╢реНрдиреЛрдВ рдХреЛ рд▓рд┐рдЦрдХрд░ рдЬреЛ рдЪрдпрдирд┐рдд рд▓реЛрдбрд┐рдВрдЧ рдореЛрдб рдХреЗ рдЕрдиреБрд░реВрдк рд╣реИрдВ, рддреЛ рдмрд╣реБрдд рдЬрд▓реНрджреА рдпрд╣ рдПрдХ рджрд╣рдирд╢реАрд▓ рд╡рд┐рд╕реНрдлреЛрдЯ рдХреА рдУрд░ рд▓реЗ рдЬрд╛рдПрдЧрд╛:


  @Query("select c from Child c join fetch c.parent order by c.age") List<Child> findWithParentOrderByAge(); @Query("select c from Child c join fetch c.toys order by c.age") List<Child> findWithToysOrderByAge(); @Query("select c from Child c join fetch c.parent join fetch c.toys") List<Child> findWithParentAndToys(); //... 

рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХрд╛ рдПрдХ рд╕рд░рд▓ рдФрд░ рд╕реБрд░реБрдЪрд┐рдкреВрд░реНрдг рддрд░реАрдХрд╛ рд╣реИ: SQL / HQL рдФрд░ рдЯреЗрдореНрдкрд▓реЗрдЯ рдЗрдВрдЬрди рдХрд╛ рдПрдХ рд╕рдВрдпреЛрдЬрдиред "рдлреНрд░реАрдорд╛рд░реНрдХрд░" рдХрд╛ рдЙрдкрдпреЛрдЧ рдореЗрд░реА рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдкрд░ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рд╣рд╛рд▓рд╛рдВрдХрд┐ рдЕрдиреНрдп рд╕рдорд╛рдзрд╛рдиреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ ("рдЯрд┐рдорд▓рд┐рдлрд╝", "рдорд╕реНрдЯреИрд╢", рдЖрджрд┐)ред


рдЪрд▓рд┐рдП рдмрдирд╛рдирд╛ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдореЗрдВ рдПрдХ рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдХреНрд╡реЗрд░реА рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдЬреЛ *.hql.ftl рдпрд╛ *.sql.ftl (рдпрджрд┐ "рд╢реБрджреНрдз" рдПрд╕рдХреНрдпреВрдПрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░) рдкреНрд░рд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИ:


 #* @vtlvariable name="fetchParent" type="java.lang.Boolean" *# #* @vtlvariable name="fetchToys" type="java.lang.Boolean" *# #* @vtlvariable name="orderByAge" type="java.lang.Boolean" *# select child from Child child #if($fetchParent) left join fetch child.parent #end #if($fetchToys) left join fetch child.toys #end #if($orderByAge) order by child.age #end 

рдЕрдм рдЖрдкрдХреЛ рдПрдХ рд╣реИрдВрдбрд▓рд░ рдХреА рдЬрд░реВрд░рдд рд╣реИ:


 @Component @RequiredArgsConstructor public class TemplateParser { private final Configuration configuration; @SneakyThrows public String prepareQuery(String templateName, Map<String, Object> params){ Template template = configuration.getTemplate(templateName); return FreeMarkerTemplateUtils.processTemplateIntoString(template, params); } } 

рдХреБрдЫ рднреА рдЬрдЯрд┐рд▓ рдирд╣реАрдВ рд╣реИред рднрдВрдбрд╛рд░ рдХреЗ рд▓рд┐рдП рд╣реЛ рд░рд╣реА рд╣реИред рдЬрд╛рд╣рд┐рд░ рд╣реИ, JpaRepository рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рд╡рд╛рд▓рд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рд╣рдореЗрдВ рд╕реВрдЯ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред рдЗрд╕рдХреЗ рдмрдЬрд╛рдп, рд╣рдо рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рд░рд┐рдкреЛрдЬрд┐рдЯрд░реА рдмрдирд╛рдиреЗ рдХреЗ рдЕрд╡рд╕рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ:


 public interface ChildRepositoryCustom { List<Child> findAll(boolean fetchParent, boolean fetchToys, boolean order); } @RequiredArgsConstructor public class ChildRepositoryImpl extends BaseDao implements ChildRepositoryCustom { private final TemplateParser templateParser; @Override public List<Child> findAll(boolean fetchParent, boolean fetchToys, boolean order) { Map<String, Object> params = new HashMap<>(); params.put("fetchParent", fetchParent); params.put("fetchToys", fetchToys); params.put("orderByAge", orderByAge); String query = templateParser.prepareQuery(BASE_CHILD_TEMPLATE.name, params); return em.createQuery(query, Child.class).getResultList(); } @RequiredArgsConstructor enum RepositoryTemplates { BASE_CHILD_TEMPLATE("BaseChildTemplate.hql.ftl"); public final String name; } } 

findUsingTemplate рд╕реЗ findUsingTemplate рд╡рд┐рдзрд┐ рдХреЛ рд╕реБрд▓рдн рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП ChildRepository рдЖрдкрдХреЛ рдпрд╣ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ:


 public interface ChildRepository extends BaseJpaRepository<Child, Long>, ChildRepositoryCustom { //... } 

рдирд╛рдо рд╕реЗ рдЬреБрдбрд╝реА рдПрдХ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╡рд┐рд╢реЗрд╖рддрд╛

рд╡рд╕рдВрдд рд╣рдорд╛рд░реА рдХрдХреНрд╖рд╛ рдФрд░ рдЗрдВрдЯрд░рдлреЗрд╕ рдХреЛ рдХреЗрд╡рд▓ рд╕рд╣реА рдирд╛рдо рдХреЗ рд╕рд╛рде рдЬреЛрдбрд╝ рджреЗрдЧрд╛:


  • ChildRepository
  • рдЪрд╛рдЗрд▓реНрдбрд░реЗрдкреЛрд╕рд┐рдЯрд░реА рдХрд╕реНрдЯрдо
  • рдЪрд╛рдЗрд▓реНрдбрд░реЗрдкреЛрд╕рд┐рдЯрд░реА рдЗрдВрдкреНрд▓рд╛рдВрдЯ

рдЗрд╕реЗ рдпрд╛рдж рд░рдЦреЗрдВ, рдХреНрдпреЛрдВрдХрд┐ рдирд╛рдо рдореЗрдВ рддреНрд░реБрдЯрд┐ рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдПрдХ рдЕрдирдЬрд╛рдиреЗ рдЕрдкрд╡рд╛рдж рдХреЛ рдлреЗрдВрдХ рджрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдЬрд┐рд╕рд╕реЗ рддреНрд░реБрдЯрд┐ рдХреЗ рдХрд╛рд░рдг рдХреЛ рд╕рдордЭрдирд╛ рдЕрд╕рдВрднрд╡ рд╣реИред


рдЕрдм рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЖрдк рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЛ рд╣рд▓ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдорд╛рди рд▓реАрдЬрд┐рдП рдХрд┐ рд╣рдореЗрдВ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛-рдЪрдпрдирд┐рдд рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдЪрдпрди рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рджреВрд╕рд░реЗ рд╢рдмреНрджреЛрдВ рдореЗрдВ, рдпрджрд┐ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдиреЗ "рд╕реЗ" рдФрд░ "рд╕реЗ" рддрд╛рд░реАрдЦреЛрдВ рдХреЛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдирд╣реАрдВ рдХрд┐рдпрд╛ рд╣реИ, рддреЛ рдХреЛрдИ рд╕рдордп рдлрд╝рд┐рд▓реНрдЯрд░ рдирд╣реАрдВ рд╣реЛрдЧрд╛ред рдпрджрд┐ рдХреЗрд╡рд▓ рджрд┐рдирд╛рдВрдХ "рд╕реЗ" рдпрд╛ рдХреЗрд╡рд▓ рджрд┐рдирд╛рдВрдХ "рд╕реЗ" рдирд┐рд░реНрджрд┐рд╖реНрдЯ рд╣реИ, рддреЛ рдлрд╝рд┐рд▓реНрдЯрд░рд┐рдВрдЧ рдПрдХ рддрд░рдлрд╝рд╛ рд╣реЛрдЧреАред рдпрджрд┐ рджреЛрдиреЛрдВ рддрд┐рдерд┐рдпрд╛рдВ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХреА рдЬрд╛рддреА рд╣реИрдВ, рддреЛ рдХреЗрд╡рд▓ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рддрд┐рдерд┐рдпреЛрдВ рдХреЗ рдмреАрдЪ рд░рд┐рдХреЙрд░реНрдб рдЪрдпрди рдореЗрдВ рдЖрдПрдЧрд╛:


 @Getter @RequiredArgsConstructor public class RequestDto { private final LocalDate from; private final LocalDate to; public boolean hasDateFrom() { return from != null; } public boolean hasDateTo() { return to != null; } } @Override public List<Child> findAll(ChildRequest request) { Map<String, Object> params = singletonMap("request", request); String query = templateParser.prepareQuery(TEMPLATE.name, params); return em.createQuery(query, Child.class).getResultList(); } 

рдЕрдм рдЯреЗрдореНрдкрд▓реЗрдЯ:


 <#-- @ftlvariable name="request" type="...RequestDto" --> select child from Child child <#if request.hasDateFrom() && request.hasDateTo()> where child.birthDate >= :dateFrom and child.birthDate <= :dateTo <#elseif request.hasDateFrom()> where child.birthDate >= :dateFrom <#elseif request.hasDateTo()> where child.birthDate <= :dateTo </#if> 

рдУрд░реЗрдХрд▓ рдФрд░ рдПрдирд╡реАрдПрд▓


рд╕рд╛рд░ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ:


 @Entity public class DailyRecord { @Id private Long id; @Column private String currency; @Column(name = "record_rate") private BigDecimal rate; @Column(name = "fixed_rate") private BigDecimal fxRate; @Setter(value = AccessLevel.PRIVATE) @Formula("select avg(r.record_rate) from daily_record r where r.currency = currency") private BigDecimal avgRate; } 

рдЗрд╕ рдЗрдХрд╛рдИ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреНрд╡реЗрд░реА рдореЗрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ (DBMS, рдЬреИрд╕рд╛ рдХрд┐ рд╣рдо рдпрд╛рдж рдХрд░рддреЗ рд╣реИрдВ, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ Oracle рд╣реИ):


 @Query("select nvl(record.fxRate, record.avgRate) " + " from DailyRecord record " + "where record.currency = :currency") BigDecimal findRateByCurrency(@Param("currency") String currency); 

рдпрд╣ рдПрдХ рдХрд╛рдордХрд╛рдЬреА, рд╡реИрдз рдЕрдиреБрд░реЛрдз рд╣реИред рд▓реЗрдХрд┐рди рдЗрд╕рдХреЗ рд╕рд╛рде рдПрдХ рдЫреЛрдЯреА рд╕рдорд╕реНрдпрд╛ рд╣реИ, рдЬрд┐рд╕реЗ SQL рд╡рд┐рд╢реЗрд╖рдЬреНрдЮ рд╢рд╛рдпрдж рдЗрдВрдЧрд┐рдд рдХрд░реЗрдВрдЧреЗред рддрдереНрдп рдпрд╣ рд╣реИ рдХрд┐ рдУрд░реЗрдХрд▓ рдореЗрдВ nvl рдЖрд▓рд╕реА рдирд╣реАрдВ рд╣реИред рджреВрд╕рд░реЗ рд╢рдмреНрджреЛрдВ рдореЗрдВ, рдЬрдм рд╣рдо findRateByCurrency рд╡рд┐рдзрд┐ рдХреЛ рдХреЙрд▓ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ findRateByCurrency рд▓реЙрдЧ findRateByCurrency рд╣реЛрдЧрд╛


 select nvl( dr.fixed_rate, select avg(r.record_rate) from daily_record r where r.currency = dr.currency ) from daily_record dr where dr.currency = ? 

рднрд▓реЗ рд╣реА dr.fixed_rate рдорд╛рди рдореМрдЬреВрдж рд╣реЛ, рд▓реЗрдХрд┐рди DBMS рдЕрднреА рднреА nvl рдореЗрдВ рджреВрд╕рд░реА рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рджреНрд╡рд╛рд░рд╛ рд▓реМрдЯрд╛рдП рдЧрдП рдореВрд▓реНрдп рдХреА рдЧрдгрдирд╛ рдХрд░рддрд╛ рд╣реИ, рдЬреЛ рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ


 select avg(r.record_rate) from daily_record r where r.currency = dr.currency) 

рдкрд╛рдардХ рд╢рд╛рдпрдж рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЬрд╛рдирддрд╛ рд╣реИ рдХрд┐ рдЕрдиреБрд░реЛрдз рдХреЗ рдЕрдирд╛рд╡рд╢реНрдпрдХ рднрд╛рд░ рдХреЛ рдХреИрд╕реЗ рдЪрдХрдорд╛ рджреЗрдирд╛ рд╣реИ: рдмреЗрд╢рдХ, рдпрд╣ рдХреАрд╡рд░реНрдб nvl , рдЬреЛ рдЕрдкрдиреЗ рдЖрд▓рд╕реНрдп рдХреЗ рд╕рд╛рде nvl рдЕрдиреБрдХреВрд▓рддрд╛ рдХреА рддреБрд▓рдирд╛ рдХрд░рддрд╛ рд╣реИ, рд╕рд╛рде рд╣реА 2 рд╕реЗ рдЕрдзрд┐рдХ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐рдпреЛрдВ рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рд╣реИред рдЪрд▓реЛ рд╣рдорд╛рд░реЗ рдЕрдиреБрд░реЛрдз рдХреЛ рд╕рд╣реА рдХрд░реЗрдВ:


 @Query("select coalesce(record.fxRate, record.avgRate) " + " from DailyRecord record " + "where record.currency = :currency") BigDecimal findRateByCurrency(@Param("currency") String currency); 

рдФрд░ рдлрд┐рд░, рдЬреИрд╕рд╛ рдХрд┐ рд╡реЗ рдХрд╣рддреЗ рд╣реИрдВ, рдЕрдЪрд╛рдирдХ:


 select nvl(dr.fixed_rate, select avg(r.record_rate) from daily_record r where r.currency = dr.currency) from daily_record dr where dr.currency = ? 

рдЕрдиреБрд░реЛрдз рд╡рд╣реА рд░рд╣рд╛ред рдРрд╕рд╛ рдЗрд╕рд▓рд┐рдП рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдмреЙрдХреНрд╕ рд╕реЗ рджреИрд╡реАрдп рдмреЛрд▓реА рдПрдХ nvl рд╢реНрд░реГрдВрдЦрд▓рд╛ рдореЗрдВ рддрдмреНрджреАрд▓ рд╣реЛ nvl рд╣реИред


рдЯрд┐рдкреНрдкрдгреА

рдпрджрд┐ рдЖрдк рдЗрд╕ рд╡реНрдпрд╡рд╣рд╛рд░ рдХреЛ рдкреБрди: рдЙрддреНрдкрдиреНрди рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ CustomOracleDialect рд╡рд░реНрдЧ рдХреЗ рдирд┐рд░реНрдорд╛рддрд╛ рдореЗрдВ рджреВрд╕рд░реА рдкрдВрдХреНрддрд┐ рд╣рдЯрд╛рдПрдВ рдФрд░ DailyRecordRepositoryTest::findRateByCurrency


рдЗрд╕реЗ рдЪрдХрдорд╛ рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдкрдХреЛ рдЕрдкрдиреА рдмреЛрд▓реА рдмрдирд╛рдиреЗ рдФрд░ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ:


 public class CustomOracleDialect extends Oracle12cDialect { public CustomOracleDialect() { super(); registerFunction("coalesce", new StandardSQLFunction("coalesce")); } } 

рд╣рд╛рдВ, рдпрд╣ рдмрд╣реБрдд рдЖрд╕рд╛рди рд╣реИред рдЕрдм рд╣рдо рдмрдирд╛рдИ рдЧрдИ рдмреЛрд▓реА рдХреЛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдкрд░ рдмрд╛рдБрдзрддреЗ рд╣реИрдВ:


 spring: jpa: database-platform: com.luxoft.logeek.config.CustomOracleDialect 

рдПрдХ рдФрд░ (рдкрджрд╛рд╡рдирдд) рддрд░реАрдХрд╛:
 spring: jpa: properties: hibernate.dialect: com.luxoft.logeek.config.CustomOracleDialect 

рдЕрдиреБрд░реЛрдз рдХреЛ рдмрд╛рд░-рдмрд╛рд░ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рд╕реЗ рдкреНрд░рддрд┐рд╖реНрдард┐рдд рдХреЛрд▓реЗрд╕рд╕реНрдХ рдкреНрд░рд╛рдкреНрдд рд╣реЛрддрд╛ рд╣реИ:


 select coalesce(dr.fixed_rate, select avg(r.record_rate) from daily_record r where r.currency = dr.currency) from daily_record dr where dr.currency = ? 

рдУрд░реЗрдХрд▓ рдФрд░ рдкреЗрдЬ рдЕрдиреБрд░реЛрдз


рд╕рд╛рдорд╛рдиреНрдп рддреМрд░ рдкрд░, рдмреЛрд▓реА рдХреЗ рдкреВрд░рд╛ рд╣реЛрдиреЗ рд╕реЗ рдХреНрд╡реЗрд░реА рд╣реЗрд░рдлреЗрд░ рдХреЗ рд▓рд┐рдП рд╕рдореГрджреНрдз рдЕрд╡рд╕рд░ рдорд┐рд▓рддреЗ рд╣реИрдВред рдЕрдХреНрд╕рд░ рдПрдХ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдФрд░ рдПрдХ рд╡реЗрдм рдЪреЗрд╣рд░реЗ рдХреЛ рд╡рд┐рдХрд╕рд┐рдд рдХрд░рддреЗ рд╕рдордп, рдбреЗрдЯрд╛ рдХреЗ рдкреЗрдЬ-рд╡рд╛рд░ рдЕрдкрд▓реЛрдб рдХрд░рдиреЗ рдХрд╛ рдХрд╛рд░реНрдп рд╕рд╛рдордирд╛ рдХрд░рдирд╛ рдкрдбрд╝рддрд╛ рд╣реИред рджреВрд╕рд░реЗ рд╢рдмреНрджреЛрдВ рдореЗрдВ, рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рд╣рдорд╛рд░реЗ рдХрдИ рд╕реМ рд╣рдЬрд╛рд░ рд░рд┐рдХреЙрд░реНрдб рд╣реИрдВ, рд▓реЗрдХрд┐рди рд╡реЗ рдкреНрд░рддрд┐ рдкреГрд╖реНрда 10/50/100 рд░рд┐рдХреЙрд░реНрдб рдХреЗ рдкреИрдХ рдореЗрдВ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВред рдмреЙрдХреНрд╕ рд╕реЗ рд╕реНрдкреНрд░рд┐рдВрдЧ рдбреЗрдЯ рдбреЗрд╡рд▓рдкрд░ рдХреЛ рд╕рдорд╛рди рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдкреНрд░рджрд╛рди рдХрд░рддреА рд╣реИ:


 @Query("select new com.luxoft.logeek.data.BriefChildData(" + "c.id, " + "c.age " + ") from Child c " + " join c.parent p " + "where p.name = ''") Page<BriefChildData> browse(Pageable pageable); 

рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдореЗрдВ рдПрдХ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдХрдореА рд╣реИ, рдЕрд░реНрдерд╛рддреН, рджреЛ рдкреНрд░рд╢реНрдиреЛрдВ рдХрд╛ рдирд┐рд╖реНрдкрд╛рджрди, рдЬрд┐рдирдореЗрдВ рд╕реЗ рдкрд╣рд▓рд╛ рдбреЗрдЯрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИ, рдФрд░ рджреВрд╕рд░рд╛ рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рдЙрдирдХреА рдХреБрд▓ рд╕рдВрдЦреНрдпрд╛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддрд╛ рд╣реИ ( Page рдСрдмреНрдЬреЗрдХреНрдЯ рдореЗрдВ рдбреЗрдЯрд╛ рдХреА рдХреБрд▓ рдорд╛рддреНрд░рд╛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдпрд╣ рдЖрд╡рд╢реНрдпрдХ рд╣реИ)ред рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдЗрд╕ рд╡рд┐рдзрд┐ рдХреЗ рд▓рд┐рдП рдПрдХ рдХреЙрд▓ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЕрдиреБрд░реЛрдз рджреЗрддрд╛ рд╣реИ (p6spy рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд▓реЙрдЧрд┐рдВрдЧ):


 select * from ( select c.id, c.age from child c inner join parent p on c.parent_id = p.id where p.name = '' ) where rownum <= 3; select count(c.id) from child c inner join parent p on c.parent_id = p.id where p.name = '' 

рдпрджрд┐ рдХреНрд╡реЗрд░реА рднрд╛рд░реА рд╣реИ (рдХрдИ рддрд╛рд▓рд┐рдХрд╛рдУрдВ рдХреЛ рдПрдХ рдЧреИрд░-рдЕрдиреБрдХреНрд░рдорд┐рдХ рд╕реНрддрдВрдн рд╕реЗ рдЬреЛрдбрд╝рд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдмрд╕ рдмрд╣реБрдд рд╕рд╛рд░реЗ рдЬреЛрдбрд╝, рдПрдХ рдХрдард┐рди рдЪрдпрди рд╕реНрдерд┐рддрд┐, рдЖрджрд┐), рддреЛ рдпрд╣ рдПрдХ рд╕рдорд╕реНрдпрд╛ рдмрди рд╕рдХрддреА рд╣реИред рд▓реЗрдХрд┐рди рдЪреВрдВрдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдУрд░реЗрдХрд▓ рд╣реИ, рддреЛ рдЖрдк рдПрдХ рдЕрдиреБрд░реЛрдз рдХреЗ рд╕рд╛рде рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдкрдВрдХреНрддрд┐рдмрджреНрдз рдЫрджреНрдо-рд╕реНрддрдВрдн рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ред


рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдЕрдкрдиреА рдмреЛрд▓реА рд╕рдорд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдФрд░ рд╕рднреА рд░рд┐рдХреЙрд░реНрдбреЛрдВ рдХреЛ рдЧрд┐рдирдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рд╡рд░реНрдгрди рдХрд░реЗрдВ:


 public class CustomOracleDialect extends Oracle12cDialect { public CustomOracleDialect() { super(); registerFunction("coalesce", new StandardSQLFunction("coalesce")); registerFunction("total_count", new TotalCountFunc()); } } public class TotalCountFunc implements SQLFunction { @Override public boolean hasArguments() { return true; } @Override public boolean hasParenthesesIfNoArguments() { return true; } @Override public Type getReturnType(Type type, Mapping mapping) { return StandardBasicTypes.LONG; } @Override public String render(Type type, List arguments, SessionFactoryImplementor factory) { if (arguments.size() != 1) { throw new IllegalArgumentException("Only 1 argument acceptable"); } return " count(" + arguments.get(0) + ") over () "; } } 

рдЕрдм рдПрдХ рдирдИ рдХреНрд╡реЗрд░реА ( ChildRepositoryImpl рд╡рд░реНрдЧ рдореЗрдВ) ChildRepositoryImpl :


 @Override public Page<BriefChildData> browseWithTotalCount(Pageable pageable) { String query = "select " + " c.id as id," + " c.age as age, " + " total_count(c.id) as totalCount" + " from Child c " + "join c.parent p " + "where p.name = ''"; List<BriefChildData> list = em.unwrap(Session.class) .createQuery(query) .setFirstResult((int) pageable.getOffset()) .setMaxResults(pageable.getPageSize()) .setResultTransformer(Transformers.aliasToBean(BriefChildData.class)) .getResultList(); if (list.isEmpty()) { return new PageImpl(Collections.emptyList()); } long totalCount = list.get(0).getTotalCount(); return new PageImpl<>(list, pageable, totalCount); } 

рдЗрд╕ рдХреЛрдб рдХреЛ рдХреЙрд▓ рдХрд░рддреЗ рд╕рдордп, рдПрдХ рдЕрдиреБрд░реЛрдз рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛


 select * from (select c.id, c.age, count(c.id) over () -- <----- from child c inner join parent p on c.parent_id = p.id where p.name = '') where rownum <= 3 

рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ count(c.id) over () рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ count(c.id) over () рдЖрдк рдбреЗрдЯрд╛ рдХреА рдХреБрд▓ рд░рд╛рд╢рд┐ рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕реЗ PageImpl рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдХреЛ рдкрд╛рд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдбреЗрдЯрд╛ рд╡рд░реНрдЧ рд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдбреЗрдЯрд╛ рд╢реНрд░реЗрдгреА рдореЗрдВ рдХрд┐рд╕реА рдЕрдиреНрдп рдлрд╝реАрд▓реНрдб рдХреЛ рд╢рд╛рдорд┐рд▓ рдХрд┐рдП рдмрд┐рдирд╛ рдЗрд╕реЗ рдЕрдзрд┐рдХ рд╕реБрд░реБрдЪрд┐рдкреВрд░реНрдг рдврдВрдЧ рд╕реЗ рдХрд░рдиреЗ рдХрд╛ рдПрдХ рддрд░реАрдХрд╛ рд╣реИ, рдЗрд╕реЗ рд╣реЛрдорд╡рд░реНрдХ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ :) рдЖрдк ProjectionVsDataTest рдкрд░реАрдХреНрд╖рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕рдорд╛рдзрд╛рди рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред


рдЕрдиреБрдХреВрд▓рди рдХреЗ рдиреБрдХрд╕рд╛рди


рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдУрд░реЗрдХрд▓ рдФрд░ рд╕реНрдкреНрд░рд┐рдВрдЧ рдбреЗрдЯ рдХреЗ рд╕рд╛рде рдПрдХ рдЕрдЪреНрдЫрд╛ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рд╣реИред рд╣рдорд╛рд░рд╛ рдХрд╛рд░реНрдп рдЗрд╕ рддрд░рд╣ рдХреЗ рдХреЛрдб рдХреЗ рдкреНрд░рджрд░реНрд╢рди рдореЗрдВ рд╕реБрдзрд╛рд░ рдХрд░рдирд╛ рд╣реИ:


 List<Long> ids = getIds(); ids.stream() .map(repository::findById) .filter(Optional::isPresent) .map(Optional::get) .forEach(this::sendToSchool); 

рдиреБрдХрд╕рд╛рди рд╕рддрд╣ рдкрд░ рд╣реИ: рдбреЗрдЯрд╛рдмреЗрд╕ рдкреНрд░рд╢реНрдиреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдЕрджреНрд╡рд┐рддреАрдп рдХреБрдВрдЬрд┐рдпреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХреЗ рдмрд░рд╛рдмрд░ рд╣реИред рдЗрд╕ рдХрдард┐рдирд╛рдИ рдкрд░ рдХрд╛рдмреВ рдкрд╛рдиреЗ рдХреА рдПрдХ рдЬреНрдЮрд╛рдд рд╡рд┐рдзрд┐ рд╣реИ:


 List<Long> ids = getIds(); repository .findAllById(ids) .forEach(this::sendToSchool); 

рдПрдХрд╛рдзрд┐рдХ рдирдореВрдиреЗ рдХрд╛ рд▓рд╛рдн рд╕реНрдкрд╖реНрдЯ рд╣реИ: рдпрджрд┐ рдкрд╣рд▓реЗ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдлреЙрд░реНрдо рдХреЗ рдХрдИ рд╕рдорд╛рди рдкреНрд░рд╢реНрди рдереЗ


 select p.* from Pupil p where p.id = 1 select p.* from Pupil p where p.id = 2 select p.* from Pupil p where p.id = 3 

рддрдм рдЕрдм рд╡реЗ рдПрдХ рдХреЗ рд▓рд┐рдП рдврд╣ рдЧрдП рд╣реИрдВ


 select p.* from Pupil p where p.id in (1, 2, 3, ... ) 

рдпрд╣ рдЖрд╕рд╛рди рд╣реЛ рдЧрдпрд╛ рд╣реИ рдФрд░ рдЕрдЪреНрдЫрд╛ рд╣реЛ рдЧрдпрд╛ рд╣реИред рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдмрдврд╝рддрд╛ рд╣реИ, рд╡рд┐рдХрд╕рд┐рдд рд╣реЛрддрд╛ рд╣реИ, рдбреЗрдЯрд╛ рдмрдврд╝рддрд╛ рд╣реИ рдФрд░ рдПрдХ рдмрд╛рд░ рдЕрдкрд░рд┐рд╣рд╛рд░реНрдп рдЖрддрд╛ рд╣реИ:


рд╕рд╛рдл рдЖрд╕рдорд╛рди рдореЗрдВ рдЕрдХреА рдЧрд░рдЬ
 ERROR - ORA-01795: maximum number of expressions in a list is 1000 

рд╣рдореЗрдВ рдлрд┐рд░ рд╕реЗ рдПрдХ рд░рд╛рд╕реНрддрд╛ рддрд▓рд╛рд╢рдиреЗ рдХреА рдЬрд░реВрд░рдд рд╣реИ (рдкреБрд░рд╛рдиреЗ рд╕рдВрд╕реНрдХрд░рдг рдкрд░ рд╡рд╛рдкрд╕ рдирд╣реАрдВ)ред рдЪреВрдВрдХрд┐ рдУрд░реЗрдХрд▓ рдЙрд╕реЗ 1000 рд╕реЗ рдЕрдзрд┐рдХ рдХреБрдВрдЬрд┐рдпреЛрдВ рдХреЛ рдЦрд┐рд▓рд╛рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рдирд╣реАрдВ рджреЗрддрд╛ рд╣реИ, рддреЛ рдЖрдк рдкреВрд░реЗ рдбреЗрдЯрд╛ рдХреЛ 1000 рд╕реЗ рдЕрдзрд┐рдХ рдирд╣реАрдВ рдХреЗ рдмрд░рд╛рдмрд░ рд╢реЗрдпрд░реЛрдВ рдореЗрдВ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдХрдИ рдкреНрд░рд╢реНрдиреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:


 List<List<Long>> idChunks = cgccLists.partition(ids, 1000); //* idChunks.forEach(idChunk -> repository.findAllById(idChunk).forEach(this::sendToSchool) ); //* cgccLists = com.google.common.collect.Lists 

рдпрд╣ рд╡рд┐рдзрд┐ рдХрд╛рдо рдХрд░рддреА рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рдереЛрдбрд╝рд╛ рдмрджрдмреВ рдЖ рд░рд╣реА рд╣реИ (рдпрд╣ рд╣реИ?): рдпрджрд┐ рдЖрдк рдЕрдиреНрдп рдЬрдЧрд╣реЛрдВ рдкрд░ рдРрд╕реА рдХрдард┐рдирд╛рдЗрдпреЛрдВ рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░рддреЗ рд╣реИрдВ рддреЛ рдЖрдкрдХреЛ рдЙрд╕реА рдмрдЧреАрдЪреЗ рдореЗрдВ рдмрд╛рдбрд╝ рд▓рдЧрд╛рдирд╛ рд╣реЛрдЧрд╛ред рдЪрд▓рд┐рдП BaseJpaRepositoryImpl рдХреЛ BaseJpaRepositoryImpl рдХрд░рдХреЗ рд╕рдорд╕реНрдпрд╛ рдХреЛ рдЕрдзрд┐рдХ рд╕реБрд░реБрдЪрд┐рдкреВрд░реНрдг рдврдВрдЧ рд╕реЗ рд╣рд▓ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВред рдРрд╕рд╛ рдХрд░рдиреЗ рдХрд╛ рд╕рдмрд╕реЗ рдЖрд╕рд╛рди рддрд░реАрдХрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдЙрдкрд░реЛрдХреНрдд рддрд░реНрдХ рдХреЛ рднреАрддрд░ рд╕реЗ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдирд╛, рдЗрд╕реЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╕реЗ рдЫрд┐рдкрд╛рдПрдВ:


 @Override public List<T> findAllById(Iterable<ID> ids) { Assert.notNull(ids, "The given Iterable of Id's must not be null!"); Set<ID> idsCopy = Sets.newHashSet(ids); if (idsCopy.size() <= OracleConstants.MAX_IN_COUNT) { return super.findAllById(ids); } return findAll(idsCopy); } private List<T> findAll(Collection<ID> ids) { List<List<ID>> idChunks = Lists.partition(new ArrayList<>(ids), 1000); return idChunks .stream() .map(this::findAllById) .flatMap(List::stream) .collect(Collectors.toList()); } 

рдпрд╣ рдмреЗрд╣рддрд░ рд╣реЛ рдЧрдпрд╛: рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдордиреЗ рдмреБрдирд┐рдпрд╛рджреА рдврд╛рдВрдЪреЗ рдХреА рдкрд░рддреЛрдВ рд╕реЗ рдХрд╛рдо рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдХреЛрдб рдХреЛ рд╕рд╛рдл рдХрд┐рдпрд╛, рдФрд░ рджреВрд╕рд░реА рдмрд╛рдд, рд╣рдордиреЗ рдЕрдкрдиреЗ рд╕рдорд╛рдзрд╛рди рдХреЗ рджрд╛рдпрд░реЗ рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рд╕рднреА рдкрд░рд┐рдпреЛрдЬрдирд╛ рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдореЗрдВ рдХрд┐рдпрд╛ рдЬреЛ BaseJpaRepository рд╡рд┐рд╕реНрддрд╛рд░ BaseJpaRepository ред рдЗрд╕рдХреЗ рдиреБрдХрд╕рд╛рди рднреА рд╣реИрдВред рдореБрдЦреНрдп рдПрдХ рдХреЗ рдмрдЬрд╛рдп рдХрдИ рдЕрдиреБрд░реЛрдз рд╣реИрдВ, рдФрд░ рдпрд╣ рднреА (рдореБрдЦреНрдп рдПрдХ рд╕реЗ рдЙрдкрдЬрд╛ рд╣реИ) - рдХреБрдВрдЬреА рдХреЛ рдлрд╝рд┐рд▓реНрдЯрд░ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдпрджрд┐ рдРрд╕рд╛ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдПрдХ рд╣реА рдХреБрдВрдЬреА рдЕрд▓рдЧ-рдЕрд▓рдЧ idChunks рдореЗрдВ рджрд┐рдЦрд╛рдИ рджреЗ рд╕рдХрддреА рд╣реИред рдпрд╣, рдмрджрд▓реЗ рдореЗрдВ, рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рдПрдХ рд╣реА рдЗрдХрд╛рдИ рдХреЛ рджреЛ рдмрд╛рд░ рд╕реВрдЪреА рдореЗрдВ рд╢рд╛рдорд┐рд▓ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдФрд░, рддрджрдиреБрд╕рд╛рд░, рджреЛ рдмрд╛рд░ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рд╣рдореЗрдВ рдЗрд╕рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдпрд╣рд╛рдВ рдПрдХ рдФрд░, рдЕрдзрд┐рдХ рдкрд░рд┐рд╖реНрдХреГрдд рд╕рдорд╛рдзрд╛рди рд╣реИ:


 @Override public List<T> findAllById(Iterable<ID> ids) { Assert.notNull(ids, "The given Iterable of Id's must not be null!"); ArrayList<ID> idsCopy = Lists.newArrayList(ids); if (idsCopy.size() <= OracleConstants.MAX_IN_COUNT) { return super.findAllById(ids); } return findAll(idsCopy); } private List<T> findAll(ArrayList<ID> ids) { CriteriaBuilder cb = entityManager.getCriteriaBuilder(); CriteriaQuery<T> query = cb.createQuery(getDomainClass()); Root<T> from = query.from(getDomainClass()); Predicate predicate = toPredicate(cb, ids, from); query = query.select(from).where(predicate); return entityManager.createQuery(query).getResultList(); } private Predicate toPredicate(CriteriaBuilder cb, ArrayList<ID> ids, Root<T> root) { List<List<ID>> chunks = Lists.partition(ids, OracleConstants.MAX_IN_COUNT); SingularAttribute<? super T, ?> id = entityInfo.getIdAttribute(); Predicate[] predicates = chunks.stream() .map(chunk -> root.get(id).in(chunk)) .toArray(Predicate[]::new); return cb.or(predicates); } 

рдпрд╣ рдХреНрд░рд╛рдЗрдЯреЗрд░рд┐рдпрд╛ рдПрдкреАрдЖрдИ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ, рдЬрд┐рд╕рд╕реЗ рдлреЙрд░реНрдо рдХреА рдПрдХ рдЕрдВрддрд┐рдо рдХреНрд╡реЗрд░реА рдмрдирд╛рдирд╛ рд╕рдВрднрд╡ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ


 select p.* from Pupil p where p.id in (1, 2, ... , 1000) or p.id in (1001, ... , 2000) or p.id in (2001, ... , 3000) 

рдПрдХ рд╕реВрдХреНрд╖реНрдорддрд╛ рд╣реИ: рдПрдХ рд╕рдорд╛рди рдЕрдиреБрд░реЛрдз рдмреЛрдЭрд┐рд▓ рдкрд░рд┐рд╕реНрдерд┐рддрд┐рдпреЛрдВ рдХреЗ рдХрд╛рд░рдг рд╕рд╛рдорд╛рдиреНрдп рд╕реЗ рдЕрдзрд┐рдХ рд╕рдордп рддрдХ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдкрд╣рд▓реА рд╡рд┐рдзрд┐ (рдХрднреА-рдХрднреА) рдмреЗрд╣рддрд░ рд╣реЛ рд╕рдХрддреА рд╣реИред


рдпрд╣ рд╕рдм, рдореБрдЭреЗ рдЖрд╢рд╛ рд╣реИ рдХрд┐ рдЙрджрд╛рд╣рд░рдг рдЖрдкрдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧреА рдереЗ рдФрд░ рд░реЛрдЬрдорд░реНрд░рд╛ рдХреЗ рд╡рд┐рдХрд╛рд╕ рдореЗрдВ рдЙрдкрдпреЛрдЧреА рдереЗред рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ рдФрд░ рдкрд░рд┐рд╡рд░реНрдзрди рдХрд╛ рд╕реНрд╡рд╛рдЧрдд рд╣реИред

Source: https://habr.com/ru/post/hi444240/


All Articles