рд╕реНрдкреНрд░рд┐рдВрдЧ рдбреЗрдЯрд╛ рдЬреЗрдкреАрдП: рдХреНрдпрд╛ рдЕрдЪреНрдЫрд╛ рд╣реИ рдФрд░ рдХреНрдпрд╛ рдмреБрд░рд╛

рдмрдЪреНрдЪрд╛ рдмреЗрдЯрд╛ рдЕрдкрдиреЗ рдкрд┐рддрд╛ рдХреЗ рдкрд╛рд╕ рдЖрдпрд╛
рдФрд░ рдмрдЪреНрдЪреЗ рд╕реЗ рдкреВрдЫрд╛
- рдЕрдЪреНрдЫрд╛ рдХреНрдпрд╛ рд╣реИ
рдФрд░ рдХреНрдпрд╛ рдмреБрд░рд╛ рд╣реИ

рд╡реНрд▓рд╛рджрд┐рдореАрд░ рдорд╛рдпрд╛рдХреЛрд╡рд╕реНрдХреА


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


рд▓реЗрдЦ рдореЗрдВ рд╡рд░реНрдгрд┐рдд рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреЛ рд╕рдВрджрд░реНрдн рджреНрд╡рд╛рд░рд╛ рд╕реБрд▓рдн, рдкрд░реАрдХреНрд╖рдг рд╡рд╛рддрд╛рд╡рд░рдг рдореЗрдВ рдЪрд▓рд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред


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

рд╕реНрдкреНрд░рд┐рдВрдЧ рдбреЗрдЯрд╛ JPA 2 рдХреЗ рд╕рдВрд╕реНрдХрд░рдгреЛрдВ рдореЗрдВред * рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдореБрдЦреНрдп рдЗрдВрдЯрд░рдлрд╝реЗрд╕, рдЕрд░реНрдерд╛рддреН CrudRepository , рдЬрд┐рд╕рдореЗрдВ рд╕реЗ JpaRepository рдХреЛ рд╡рд┐рд░рд╛рд╕рдд рдореЗрдВ рдорд┐рд▓рд╛ рд╣реИ, рдореЗрдВ JpaRepository ред рд╕рдВрд╕реНрдХрд░рдгреЛрдВ рдореЗрдВ 1. * рдореБрдЦреНрдп рд╡рд┐рдзрд┐рдпрд╛рдБ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рджрд┐рдЦрддреА рд╣реИрдВ:


 public interface CrudRepository<T, ID> { T findOne(ID id); List<T> findAll(Iterable<ID> ids); } 

рдирдП рд╕рдВрд╕реНрдХрд░рдгреЛрдВ рдореЗрдВ:


 public interface CrudRepository<T, ID> { Optional<T> findById(ID id); List<T> findAllById(Iterable<ID> ids); } 

рддреЛ рдЪрд▓рд┐рдП рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВред


t рд╕реЗ рдЪреБрдиреЗрдВред рдЬрд╣рд╛рдВ t.id рд╕реЗ (...)


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


 @Query("select ba from BankAccount ba where ba.user.id in :ids") List<BankAccount> findByUserIds(@Param("ids") List<Long> ids); @Query("select ba from BankAccount ba where ba.user.id in :ids") List<BankAccount> findByUserIds(@Param("ids") Set<Long> ids); 

рдпреЗ рдХрд╛рдо рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рдЙрдкрдпреБрдХреНрдд рдЕрдиреБрд░реЛрдз рд╣реИрдВ, рдХреЛрдИ рдкрдХрдбрд╝ рдпрд╛ рдкреНрд░рджрд░реНрд╢рди рд╕рдорд╕реНрдпрд╛ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдПрдХ рдЫреЛрдЯреА рд╕реА, рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЕрд╕рдВрдЧрдд рдХрдореА рд╣реИред


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

рдиреБрдХрд╕рд╛рди рдпрд╣ рд╣реИ рдХрд┐ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреБрдВрдЬреА рдХреЛ рдкреНрд░рд╕рд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рд╕рдВрдХреАрд░реНрдг рд╣реИред "рддреЛ рдХреНрдпрд╛?" - рдЖрдк рдХрд╣рддреЗ рд╣реИрдВред "рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рд╕реВрдЪреА, рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рд╕реЗрдЯ, рдореБрдЭреЗ рдпрд╣рд╛рдБ рдХреЛрдИ рд╕рдорд╕реНрдпрд╛ рдирд╣реАрдВ рджрд┐рдЦ рд░рд╣реА рд╣реИред" рд╣рд╛рд▓рд╛рдВрдХрд┐, рдЕрдЧрд░ рд╣рдо рд░реВрдЯ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЗ рддрд░реАрдХреЛрдВ рдХреЛ рджреЗрдЦрддреЗ рд╣реИрдВ рдЬреЛ рдХрдИ рдорд╛рди рд▓реЗрддреЗ рд╣реИрдВ, рддреЛ рд╣рд░ рдЬрдЧрд╣ рд╣рдо Iterable рджреЗрдЦрддреЗ рд╣реИрдВ:


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


 public List<BankAccount> findByUserId(List<Long> userIds) { Set<Long> ids = new HashSet<>(userIds); return repository.findByUserIds(ids); } // public List<BankAccount> findByUserIds(Set<Long> userIds) { List<Long> ids = new ArrayList<>(userIds); return repository.findByUserIds(ids); } 

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


рдЗрд╕рд▓рд┐рдП, Iterable рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдЕрдЪреНрдЫрд╛ рд╣реИ:


 @Query("select ba from BankAccount ba where ba.user.id in :ids") List<BankAccount> findByUserIds(@Param("ids") Iterable<Long> ids); 

ZY рдпрджрд┐ рд╣рдо *RepositoryCustom рд╕реЗ рдПрдХ рд╡рд┐рдзрд┐ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рддреЛ рдпрд╣ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ рдЖрдХрд╛рд░ рдХреА рдЧрдгрдирд╛ рдХреЛ рд╕рд░рд▓ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП Collection рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдордЭ рдореЗрдВ рдЖрддрд╛ рд╣реИ:


 public interface BankAccountRepositoryCustom { boolean anyMoneyAvailable(Collection<Long> accountIds); } public class BankAccountRepositoryImpl { @Override public boolean anyMoneyAvailable(Collection<Long> accountIds) { if (ids.isEmpty()) return false; //... } } 

рдЕрддрд┐рд░рд┐рдХреНрдд рдХреЛрдб: рдЧреИрд░-рдбреБрдкреНрд▓рд┐рдХреЗрдЯ рдХреБрдВрдЬреА


рдЕрдВрддрд┐рдо рдЦрдВрдб рдХреА рдирд┐рд░рдВрддрд░рддрд╛ рдореЗрдВ, рдореИрдВ рдПрдХ рдЖрдо рдЧрд▓рдд рдзрд╛рд░рдгрд╛ рдкрд░ рдзреНрдпрд╛рди рдЖрдХрд░реНрд╖рд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ:


 @Query("select ba from BankAccount ba where ba.user.id in :ids") List<BankAccount> findByUserIds(@Param("ids") Set<Long> ids); 

рдПрдХ рд╣реА рддреНрд░реБрдЯрд┐ рдХреЗ рдЕрдиреНрдп рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐рдпрд╛рдБ:


 Set<Long> ids = new HashSet<>(notUniqueIds); List<BankAccount> accounts = repository.findByUserIds(ids); List<Long> ids = ts.stream().map(T::id).distinct().collect(toList()); List<BankAccount> accounts = repository.findByUserIds(ids); Set<Long> ids = ts.stream().map(T::id).collect(toSet()); List<BankAccount> accounts = repository.findByUserIds(ids); 

рдкрд╣рд▓реА рдирдЬрд╝рд░ рдореЗрдВ, рдХреБрдЫ рднреА рдЕрд╕рд╛рдорд╛рдиреНрдп рдирд╣реАрдВ рд╣реИ, рд╣реИ рдирд╛?


рдЕрдкрдирд╛ рд╕рдордп рд▓реЗ рд▓реЛ, рдЕрдкрдиреЗ рд▓рд┐рдП рд╕реЛрдЪреЛ;)

HQL / JPQL рдлреЙрд░реНрдо рдХреЗ рдкреНрд░рд╢реНрди select t from t where t.field in ... рдЕрдВрддрддрдГ рдПрдХ рдХреНрд╡реЗрд░реА рдореЗрдВ рдмрджрд▓ рдЬрд╛рдПрдЧрд╛


 select b.* from BankAccount b where b.user_id in (?, ?, ?, ?, ?, тАж) 

рдЬреЛ рд╣рдореЗрд╢рд╛ рддрд░реНрдХ рдореЗрдВ рдореМрдЬреВрдж рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдХреА рдЙрдкрд╕реНрдерд┐рддрд┐ рдХреА рдкрд░рд╡рд╛рд╣ рдХрд┐рдП рдмрд┐рдирд╛ рдПрдХ рд╣реА рдмрд╛рдд рд▓реМрдЯрд╛рдПрдЧрд╛ред рдЗрд╕рд▓рд┐рдП, рдЪрд╛рдмрд┐рдпреЛрдВ рдХреА рд╡рд┐рд╢рд┐рд╖реНрдЯрддрд╛ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рдирд╣реАрдВ рд╣реИред рдПрдХ рд╡рд┐рд╢реЗрд╖ рдорд╛рдорд▓рд╛ рд╣реИ - рдУрд░реЗрдХрд▓, рдЬрд╣рд╛рдВ рдПрдХ рддреНрд░реБрдЯрд┐ рдХреА рдУрд░> 1000 рдХреБрдВрдЬреА рдХреЛ рдорд╛рд░рдирд╛ рд╣реИред рд▓реЗрдХрд┐рди рдпрджрд┐ рдЖрдк рджреЛрд╣рд░рд╛рд╡ рдХреЛ рдЫреЛрдбрд╝рдХрд░ рдЪрд╛рдмрд┐рдпреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХрдо рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рддреЛ рдЖрдкрдХреЛ рдЙрдирдХреА рдШрдЯрдирд╛ рдХреЗ рдХрд╛рд░рдг рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕реЛрдЪрдирд╛ рдЪрд╛рд╣рд┐рдПред рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рд╕рдВрднрд╛рд╡рдирд╛ рд╣реИ рдХрд┐ рддреНрд░реБрдЯрд┐ рдХрд╣реАрдВ рдКрдкрд░ рд╣реИред


рддреЛ рдЕрдЪреНрдЫреЗ рдХреЛрдб рдореЗрдВ Iterable рдЙрдкрдпреЛрдЧ Iterable :


 @Query("select ba from BankAccount ba where ba.user.id in :ids") List<BankAccount> findByUserIds(@Param("ids") Iterable<Long> ids); 

Samopis


рдЗрд╕ рдХреЛрдб рдкрд░ рдПрдХ рдирдЬрд╝рд░ рдбрд╛рд▓реЗрдВ рдФрд░ рдпрд╣рд╛рдВ рддреАрди рдЦрд╛рдорд┐рдпреЛрдВ рдФрд░ рдПрдХ рд╕рдВрднрд╛рд╡рд┐рдд рддреНрд░реБрдЯрд┐ рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рдПрдВ:


 @Query("from User u where u.id in :ids") List<User> findAll(@Param("ids") Iterable<Long> ids); 

рдХреБрдЫ рдФрд░ рд╕реЛрдЪреЛ
  • рд╕рдм рдХреБрдЫ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА SimpleJpaRepository::findAllById рдореЗрдВ рд▓рд╛рдЧреВ рд╣реИ SimpleJpaRepository::findAllById
  • рдЦрд╛рд▓реА рд╕реВрдЪреА рдкрд╛рд╕ рдХрд░рддреЗ рд╕рдордп рдирд┐рд╖реНрдХреНрд░рд┐рдп рдЕрдиреБрд░реЛрдз ( SimpleJpaRepository::findAllById рдПрдХ рд╕рдВрдмрдВрдзрд┐рдд рдЪреЗрдХ рд╣реИ)
  • @Query рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╡рд░реНрдгрд┐рдд рд╕рднреА рдкреНрд░рд╢реНрдиреЛрдВ рдХреЛ рд╕рдВрджрд░реНрдн рдХреЛ рдмрдврд╝рд╛рдиреЗ рдХреЗ рдЪрд░рдг рдореЗрдВ @Query рдЬрд╛рддрд╛ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рд╕рдордп рд▓рдЧрддрд╛ рд╣реИ ( SimpleJpaRepository::findAllById рд╡рд┐рдкрд░реАрдд SimpleJpaRepository::findAllById )
  • рдпрджрд┐ Oracle рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬрдм рдХреБрдВрдЬреА рд╕рдВрдЧреНрд░рд╣ рдЦрд╛рд▓реА рд╣реЛрддрд╛ рд╣реИ, рддреЛ рд╣рдореЗрдВ рддреНрд░реБрдЯрд┐ ORA-00936: missing expression рдорд┐рд▓рддреА рд╣реИ ORA-00936: missing expression (рдЬреЛ рдХрд┐ SimpleJpaRepository::findAllById рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╕рдордп рдирд╣реАрдВ рд╣реЛрдЧреА SimpleJpaRepository::findAllById , рдмрд┐рдВрджреБ 2 рджреЗрдЦреЗрдВ)

рд╣реИрд░реА рдкреЙрдЯрд░ рдФрд░ рдХрдВрдкрд╛рдЙрдВрдб рдХреА


рджреЛ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдкрд░ рдПрдХ рдирдЬрд╝рд░ рдбрд╛рд▓реЗрдВ рдФрд░ рдЕрдкрдирд╛ рдкрд╕рдВрджреАрджрд╛ рдЪреБрдиреЗрдВ:


рд╡рд┐рдзрд┐ рд╕рдВрдЦреНрдпрд╛ рдмрд╛рд░


 @Embeddable public class CompositeKey implements Serializable { Long key1; Long key2; } @Entity public class CompositeKeyEntity { @EmbeddedId CompositeKey key; } 

рд╡рд┐рдзрд┐ рд╕рдВрдЦреНрдпрд╛ рджреЛ


 @Embeddable public class CompositeKey implements Serializable { Long key1; Long key2; } @Entity @IdClass(value = CompositeKey.class) public class CompositeKeyEntity { @Id Long key1; @Id Long key2; } 

рдкрд╣рд▓реА рдирдЬрд╝рд░ рдореЗрдВ, рдХреЛрдИ рдЕрдВрддрд░ рдирд╣реАрдВ рд╣реИред рдЕрдм рдкрд╣рд▓реА рд╡рд┐рдзрд┐ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВ рдФрд░ рдПрдХ рд╕рд░рд▓ рдкрд░реАрдХреНрд╖рдг рдЪрд▓рд╛рдПрдВ:


 //case for @EmbeddedId @Test public void findAll() { int size = entityWithCompositeKeyRepository.findAllById(compositeKeys).size(); assertEquals(size, 5); } 

рдХреНрд╡реЗрд░реА рд▓реЙрдЧ рдореЗрдВ (рдЖрдк рдЗрд╕реЗ рд╕рд╣реА рд░рдЦреЗрдВ;) рд╣рдо рдЗрд╕реЗ рджреЗрдЦреЗрдВрдЧреЗ:


 select e.key1, e.key2 from CompositeKeyEntity e where e.key1 = ? and e.key2 = ? or e.key1 = ? and e.key2 = ? or e.key1 = ? and e.key2 = ? or e.key1 = ? and e.key2 = ? or e.key1 = ? and e.key2 = ? 

рдЕрдм рджреВрд╕рд░рд╛ рдЙрджрд╛рд╣рд░рдг


 //case for @Id @Id @Test public void _findAll() { int size = anotherEntityWithCompositeKeyRepository.findAllById(compositeKeys).size(); assertEquals(size, 5); } 

рдХреНрд╡реЗрд░реА рд▓реЙрдЧ рдЕрд▓рдЧ рджрд┐рдЦрддрд╛ рд╣реИ:


 select e.key1, e.key2 from CompositeKeyEntity e where e.key1=? and e.key2=? select e.key1, e.key2 from CompositeKeyEntity e where e.key1=? and e.key2=? select e.key1, e.key2 from CompositeKeyEntity e where e.key1=? and e.key2=? select e.key1, e.key2 from CompositeKeyEntity e where e.key1=? and e.key2=? select e.key1, e.key2 from CompositeKeyEntity e where e.key1=? and e.key2=? 

рдпрд╣ рдкреВрд░рд╛ рдЕрдВрддрд░ рд╣реИ: рдкрд╣рд▓реЗ рдорд╛рдорд▓реЗ рдореЗрдВ рд╣рдореЗрдВ рд╣рдореЗрд╢рд╛ 1 рдЕрдиреБрд░реЛрдз рдкреНрд░рд╛рдкреНрдд рд╣реЛрддрд╛ рд╣реИ, рджреВрд╕рд░реЗ рдореЗрдВ - n рдЕрдиреБрд░реЛрдзред
рдЗрд╕ рд╡реНрдпрд╡рд╣рд╛рд░ рдХрд╛ рдХрд╛рд░рдг SimpleJpaRepository::findAllById : SimpleJpaRepository::findAllById :


 // ... if (entityInfo.hasCompositeId()) { List<T> results = new ArrayList<>(); for (ID id : ids) { findById(id).ifPresent(results::add); } return results; } // ... 

рдЕрдиреБрд░реЛрдзреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХрд┐рддрдиреА рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ, рдЗрд╕рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдпрд╣ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдирд╛ рдХрд┐ рдЖрдкрдХреЗ рд▓рд┐рдП рдХреМрди рд╕реА рд╡рд┐рдзрд┐ рд╕рд░реНрд╡реЛрддреНрддрдо рд╣реИред


рдЕрддрд┐рд░рд┐рдХреНрдд CrudRepository :: рд╕рд╣реЗрдЬреЗрдВ


рдЕрдХреНрд╕рд░ рдХреЛрдб рдореЗрдВ рдЗрд╕ рддрд░рд╣ рдХреЗ рдПрдХ рдПрдВрдЯреАрдкреИрдЯрд░реНрди рд╣реЛрддрд╛ рд╣реИ:


 @Transactional public BankAccount updateRate(Long id, BigDecimal rate) { BankAccount account = repo.findById(id).orElseThrow(NPE::new); account.setRate(rate); return repo.save(account); } 

рдкрд╛рдардХ рд╣реИрд░рд╛рди рд╣реИ: рдПрдВрдЯреАрдкреИрдЯрд░реНрди рдХрд╣рд╛рдВ рд╣реИ? рдпрд╣ рдХреЛрдб рдмрд╣реБрдд рддрд╛рд░реНрдХрд┐рдХ рд▓рдЧрддрд╛ рд╣реИ: рд╣рдореЗрдВ рдЗрдХрд╛рдИ - рдЕрдкрдбреЗрдЯ - рд╕реЗрд╡ рдорд┐рд▓рддреА рд╣реИред рд╕реЗрдВрдЯ рдкреАрдЯрд░реНрд╕рдмрд░реНрдЧ рдХреЗ рд╕рдмрд╕реЗ рдЕрдЪреНрдЫреЗ рдШрд░реЛрдВ рдореЗрдВ рд╕рдм рдХреБрдЫ рдкрд╕рдВрдж рд╣реИред рдореИрдВ рдпрд╣ рдХрд╣рдиреЗ рдХреА рд╣рд┐рдореНрдордд рдХрд░рддрд╛ рд╣реВрдВ рдХрд┐ CrudRepository::save рдХреЛ рдХреЙрд▓ CrudRepository::save рдпрд╣рд╛рдВ рдмрд╣реБрдд рд╣реА рдЕрдЪреНрдЫрд╛ рд╣реИред


рдкрд╣рд▓рд╛: updateRate рд╡рд┐рдзрд┐ рдЯреНрд░рд╛рдВрдЬреЗрдХреНрд╢рдирд▓ рд╣реИ, рдЗрд╕рд▓рд┐рдП, рдкреНрд░рдмрдВрдзрд┐рдд рдирд┐рдХрд╛рдп рдореЗрдВ рд╕рднреА рдкрд░рд┐рд╡рд░реНрддрди рд╣рд╛рдЗрдмрд░рдиреЗрдЯ рджреНрд╡рд╛рд░рд╛ рдЯреНрд░реИрдХ рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВ рдФрд░ рдПрдХ рдЕрдиреБрд░реЛрдз рдореЗрдВ рдмрджрд▓ рдЬрд╛рддреЗ рд╣реИрдВ рдЬрдм Session::flush рдирд┐рд╖реНрдкрд╛рджрд┐рдд рд╣реЛрддрд╛ рд╣реИ, рдЬреЛ рдЗрд╕ рдХреЛрдб рдореЗрдВ рддрдм рд╣реЛрддрд╛ рд╣реИ рдЬрдм рд╡рд┐рдзрд┐ рд╕рдорд╛рдкреНрдд рд╣реЛрддреА рд╣реИред


рджреВрд╕рд░реА рдмрд╛рдд, CrudRepository::save рд╡рд┐рдзрд┐ рдкрд░ рдПрдХ рдирдЬрд╝рд░ рдбрд╛рд▓реЗрдВред рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рдЬрд╛рдирддреЗ рд╣реИрдВ, рд╕рднреА рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА SimpleJpaRepository рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдкрд░ рдЖрдзрд╛рд░рд┐рдд рд╣реИрдВред рдпрд╣рд╛рдБ CrudRepository::save рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди CrudRepository::save :


 @Transactional public <S extends T> S save(S entity) { if (entityInformation.isNew(entity)) { em.persist(entity); return entity; } else { return em.merge(entity); } } 

рдПрдХ рд╕реВрдХреНрд╖реНрдорддрд╛ рд╣реИ рдЬреЛ рд╣рд░ рдХрд┐рд╕реА рдХреЛ рдпрд╛рдж рдирд╣реАрдВ рд╣реИ: рд╣рд╛рдЗрдмрд░рдиреЗрдЯ рдШрдЯрдирд╛рдУрдВ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред рджреВрд╕рд░реЗ рд╢рдмреНрджреЛрдВ рдореЗрдВ, рдкреНрд░рддреНрдпреЗрдХ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХрд╛рд░реНрд░рд╡рд╛рдИ рдПрдХ рдРрд╕реА рдШрдЯрдирд╛ рдЙрддреНрдкрдиреНрди рдХрд░рддреА рд╣реИ рдЬреЛ рдХрддрд╛рд░рдмрджреНрдз рдФрд░ рдЙрд╕реА рдХрддрд╛рд░ рдореЗрдВ рдЕрдиреНрдп рдШрдЯрдирд╛рдУрдВ рдХреЛ рдзреНрдпрд╛рди рдореЗрдВ рд░рдЦрддреЗ рд╣реБрдП рд╕рдВрд╕рд╛рдзрд┐рдд рд╣реЛрддреА рд╣реИред рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ, EntityManager::merge рд▓рд┐рдП рдПрдХ рдХреЙрд▓ EntityManager::merge рдПрдХ MergeEvent рдЙрддреНрдкрдиреНрди рдХрд░рддрд╛ рд╣реИ, рдЬрд┐рд╕реЗ DefaultMergeEventListener::onMerge рдореЗрдВ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЗрд╕рдореЗрдВ рдЗрдХрд╛рдИ-рддрд░реНрдХ рдХреЗ рдкреНрд░рддреНрдпреЗрдХ рд░рд╛рдЬреНрдп рдХреЗ рд▓рд┐рдП рдХрд╛рдлреА рд╢рд╛рдЦрд┐рдд, рд▓реЗрдХрд┐рди рд╕рд░рд▓ рддрд░реНрдХ рд╢рд╛рдорд┐рд▓ рд╣реИрдВред рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдЗрдХрд╛рдИ рдХреЛ рдЯреНрд░рд╛рдВрд╕реЗрдХреНрд╢рдирд▓ рд╡рд┐рдзрд┐ рдХреЗ рдЕрдВрджрд░ рднрдВрдбрд╛рд░ рд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ PERSISTENT рд░рд╛рдЬреНрдп рдореЗрдВ рд╣реЛрддрд╛ рд╣реИ (рдпрд╛рдиреА, рдЕрдирд┐рд╡рд╛рд░реНрдп рд░реВрдк рд╕реЗ рдврд╛рдВрдЪреЗ рджреНрд╡рд╛рд░рд╛ рдирд┐рдпрдВрддреНрд░рд┐рдд):


 protected void entityIsPersistent(MergeEvent event, Map copyCache) { LOG.trace("Ignoring persistent instance"); Object entity = event.getEntity(); EventSource source = event.getSession(); EntityPersister persister = source.getEntityPersister(event.getEntityName(), entity); ((MergeContext)copyCache).put(entity, entity, true); this.cascadeOnMerge(source, persister, entity, copyCache); //<---- this.copyValues(persister, entity, entity, source, copyCache); //<---- event.setResult(entity); } 

рд╢реИрддрд╛рди рд╡рд┐рд╡рд░рдгреЛрдВ рдореЗрдВ рд╣реИ, рдЕрд░реНрдерд╛рддреН DefaultMergeEventListener::cascadeOnMerge рдФрд░ DefaultMergeEventListener::copyValues ред рдЖрдЗрдП, рд╣рд╛рдЗрдмрд░рдиреЗрдЯ рдХреЗ рдкреНрд░рдореБрдЦ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдореЗрдВ рд╕реЗ рдПрдХ, рд╡реНрд▓рд╛рдж рдорд┐рдЦреЗрд▓ рдХрд╛ рд╕реАрдзрд╛ рднрд╛рд╖рдг рд╕реБрдиреЗрдВ:


CopyValues тАЛтАЛрдореЗрдердб рдХреЙрд▓ рдореЗрдВ, рд╣рд╛рдЗрдбреНрд░реЗрдЯреЗрдб рд╕реНрдЯреЗрдЯ рдХреЛ рдлрд┐рд░ рд╕реЗ рдХреЙрдкреА рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдПрдХ рдирдпрд╛ рдПрд░реЗ рдХреЛ рдмреЗрд╡рдЬрд╣ рдмрдирд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП CPU рд╕рд╛рдЗрдХрд┐рд▓ рдХреЛ рдмрд░реНрдмрд╛рдж рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдпрджрд┐ рдЗрдХрд╛рдИ рдореЗрдВ рдмрд╛рд▓ рд╕рдВрдШ рд╣реИрдВ рдФрд░ рдорд░реНрдЬ рд╕рдВрдЪрд╛рд▓рди рдХреЛ рднреА рдорд╛рддрд╛-рдкрд┐рддрд╛ рд╕реЗ рдмрд╛рд▓ рд╕рдВрд╕реНрдерд╛рдУрдВ рдореЗрдВ рдХреИрд╕реНрдХреЗрдб рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдУрд╡рд░рд╣реЗрдб рдФрд░ рднреА рдЕрдзрд┐рдХ рд╣реЛрддрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдкреНрд░рддреНрдпреЗрдХ рдмрд╛рд▓ рдЗрдХрд╛рдИ рдПрдХ рдорд░реНрдЬрд╡реЗрдВрдЯ рдХрд╛ рдкреНрд░рдЪрд╛рд░ рдХрд░реЗрдЧреА рдФрд░ рдЪрдХреНрд░ рдЬрд╛рд░реА рд╣реИред

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


 @Transactional public BankAccount updateRate(Long id, BigDecimal rate) { BankAccount account = repo.findById(id).orElseThrow(NPE::new); account.setRate(rate); return account; } 

рдмреЗрд╢рдХ, рдХрд┐рд╕реА рдФрд░ рдХреЗ рдХреЛрдб рдХреЛ рд╡рд┐рдХрд╕рд┐рдд рдФрд░ рдкреНрд░реВрдл рдХрд░рддреЗ рд╕рдордп рдЗрд╕реЗ рдзреНрдпрд╛рди рдореЗрдВ рд░рдЦрдирд╛ рдЕрд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдо рд╡рд╛рдпрд░рдлреНрд░реЗрдо рд╕реНрддрд░ рдкрд░ рдкрд░рд┐рд╡рд░реНрддрди рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рддрд╛рдХрд┐ JpaRepository::save рд╡рд┐рдзрд┐ рдЕрдкрдиреЗ рд╣рд╛рдирд┐рдХрд╛рд░рдХ рдЧреБрдгреЛрдВ JpaRepository::save рдЦреЛ рджреЗред рдХреНрдпрд╛ рдпрд╣ рд╕рдВрднрд╡ рд╣реИ?


рд╣рд╛рдБ рд╢рд╛рдпрдж
 // @Transactional public <S extends T> S save(S entity) { if (entityInformation.isNew(entity)) { em.persist(entity); return entity; } else { return em.merge(entity); } } // @Transactional public <S extends T> S save(S entity) { if (entityInformation.isNew(entity)) { em.persist(entity); return entity; } else if (!em.contains(entity)) { return em.merge(entity); } return entity; } 

рдпреЗ рдмрджрд▓рд╛рд╡ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рджрд┐рд╕рдВрдмрд░ 2017 рдореЗрдВ рдХрд┐рдП рдЧрдП рдереЗ:
https://jira.spring.io/browse/DATAJPA-931
https://github.com/spring-projects/spring-data-jpa/pull/237


рд╣рд╛рд▓рд╛рдБрдХрд┐, рдкрд░рд┐рд╖реНрдХреГрдд рдкрд╛рдардХ рдХреЛ рд╢рд╛рдпрдж рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдХреБрдЫ рд╕реВрдЭ рд░рд╣рд╛ рдерд╛ред рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдпрд╣ рдкрд░рд┐рд╡рд░реНрддрди рдХреБрдЫ рднреА рдирд╣реАрдВ рддреЛрдбрд╝ рджреЗрдЧрд╛, рд▓реЗрдХрд┐рди рдХреЗрд╡рд▓ рд╕рд╛рдзрд╛рд░рдг рдорд╛рдорд▓реЗ рдореЗрдВ рдЬрдм рдХреЛрдИ рдмрд╛рд▓ рд╕рдВрд╕реНрдерд╛ рдирд╣реАрдВ рд╣реИ:


 @Entity public class BankAccount { @Id Long id; @Column BigDecimal rate = BigDecimal.ZERO; } 

рдЕрдм рдорд╛рди рд▓реАрдЬрд┐рдП рдХрд┐ рдЗрд╕рдХрд╛ рдорд╛рд▓рд┐рдХ рдЦрд╛рддреЗ рд╕реЗ рдмрдВрдзрд╛ рд╣реБрдЖ рд╣реИ:


 @Entity public class BankAccount { @Id Long id; @Column BigDecimal rate = BigDecimal.ZERO; @ManyToOne @JoinColumn(name = "user_id") User user; } 

рдПрдХ рд╡рд┐рдзрд┐ рд╣реИ рдЬреЛ рдЖрдкрдХреЛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рдЦрд╛рддреЗ рд╕реЗ рдбрд┐рд╕реНрдХрдиреЗрдХреНрдЯ рдХрд░рдиреЗ рдФрд░ рдмрд╛рдж рдореЗрдВ рдирдП рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреА рд╣реИ:


 @Transactional public BankAccount changeUser(Long id, User newUser) { BankAccount account = repo.findById(id).orElseThrow(NPE::new); account.setUser(newUser); return repo.save(account); } 

рдЕрдм рдХреНрдпрд╛ рд╣реЛрдЧрд╛? em.contains(entity) рдЬрд╛рдБрдЪ рдХрд░рдирд╛ рд╕рд╣реА рд╣реЛрдЧрд╛, рдЬрд┐рд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ em.merge(entity) рдХреЛ рдирд╣реАрдВ рдХрд╣рд╛ рдЬрд╛рдПрдЧрд╛ред рдпрджрд┐ User рдЗрдХрд╛рдИ рдХреБрдВрдЬреА рдЕрдиреБрдХреНрд░рдо (рд╕рдмрд╕реЗ рд╕рд╛рдорд╛рдиреНрдп рдорд╛рдорд▓реЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ) рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдмрдирд╛рдИ рдЧрдИ рд╣реИ, рддреЛ рдпрд╣ рддрдм рддрдХ рдирд╣реАрдВ рдмрдирд╛рдИ рдЬрд╛рдПрдЧреА рдЬрдм рддрдХ рдХрд┐ рд▓реЗрдирджреЗрди рдкреВрд░рд╛ рдирд╣реАрдВ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ (рдпрд╛ Session::flush рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ), рдЕрд░реНрдерд╛рдд рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдбреАрдИрдЯреАрдИрдбреА рд░рд╛рдЬреНрдп рдореЗрдВ рд╣реЛрдЧрд╛, рдФрд░ рдЙрд╕рдХреА рдореВрд▓ рдЗрдХрд╛рдИ ( рдЦрд╛рддрд╛) - рд╡реНрдпрдХреНрддрд┐рдЧрдд рдЕрд╡рд╕реНрдерд╛ рдореЗрдВред рдХреБрдЫ рдорд╛рдорд▓реЛрдВ рдореЗрдВ, рдпрд╣ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд▓реЙрдЬрд┐рдХ рдХреЛ рддреЛрдбрд╝ рд╕рдХрддрд╛ рд╣реИ, рдЬреЛ рдХрд┐ рд╣реБрдЖ рд╣реИ:


02/03/2018 DATAJPA-931 рдХрд╛ рд╡рд┐рд░рд╛рдо рд░рд┐рдкреЛрдЬрд┐рдЯрд░реА рдХреЗ рд╕рд╛рде рд╡рд┐рд▓рдп


рдЗрд╕ рд╕рдВрдмрдВрдз рдореЗрдВ, CrudRepository рдореЗрдВ рдореМрдЬреВрджрд╛ рд╕рдВрд╕реНрдерд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдХрд┐рдП рдЧрдП рдкреНрд░рддреНрдпрд╛рд╡рд░реНрддрди рдкреНрд░рддреНрдпрд╛рд╡рд░реНрддрди :: рд╕реЗрд╡ рдмрдирд╛рдП рдЧрдП рдФрд░ рдкрд░рд┐рд╡рд░реНрддрди рдХрд┐рдП рдЧрдП: DATAJPA-931 ред


рдЕрдВрдзрд╛ CrudRepository :: findById


рд╣рдо рд╕рдорд╛рди рдбреЗрдЯрд╛ рдореЙрдбрд▓ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░рдирд╛ рдЬрд╛рд░реА рд░рдЦрддреЗ рд╣реИрдВ:


 @Entity public class User { @Id Long id; // ... } @Entity public class BankAccount { @Id Long id; @ManyToOne @JoinColumn(name = "user_id") User user; } 

рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдореЗрдВ рдПрдХ рд╡рд┐рдзрд┐ рд╣реИ рдЬреЛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рд▓рд┐рдП рдПрдХ рдирдпрд╛ рдЦрд╛рддрд╛ рдмрдирд╛рддреА рд╣реИ:


 @Transactional public BankAccount newForUser(Long userId) { BankAccount account = new BankAccount(); userRepository.findById(userId).ifPresent(account::setUser); //<---- return accountRepository.save(account); } 

рд╕рдВрд╕реНрдХрд░рдг 2 рдХреЗ рд╕рд╛рдеред * рддреАрд░ рджреНрд╡рд╛рд░рд╛ рдЗрдВрдЧрд┐рдд рдПрдВрдЯреАрдкреИрдЯрд░реНрди рдЗрддрдирд╛ рд╣рдбрд╝рддрд╛рд▓реА рдирд╣реАрдВ рд╣реИ - рдпрд╣ рдкреБрд░рд╛рдиреЗ рд╕рдВрд╕реНрдХрд░рдгреЛрдВ рдкрд░ рдЕрдзрд┐рдХ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рджреЗрдЦрд╛ рдЬрд╛рддрд╛ рд╣реИ:


 @Transactional public BankAccount newForUser(Long userId) { BankAccount account = new BankAccount(); account.setUser(userRepository.findOne(userId)); //<---- return accountRepository.save(account); } 

рдпрджрд┐ рдЖрдкрдХреЛ "рдЖрдВрдЦ рд╕реЗ" рджреЛрд╖ рджрд┐рдЦрд╛рдИ рдирд╣реАрдВ рджреЗрддрд╛ рд╣реИ, рддреЛ рдкреНрд░рд╢реНрдиреЛрдВ рдкрд░ рдПрдХ рдирдЬрд╝рд░ рдбрд╛рд▓реЗрдВ:
 select u.id, u.name from user u where u.id = ? call next value for hibernate_sequence insert into bank_account (id, /*тАж*/ user_id) values (/*тАж*/) 

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


 @Transactional public BankAccount newForUser(Long userId) { BankAccount account = new BankAccount(); account.setUser(userRepository.getOne(userId)); //<---- return accountRepository.save(account); } 

JpaRepository::getOne рдЙрд╕ рдХреБрдВрдЬреА рдкрд░ рдПрдХ рдЖрд╡рд░рдг рджреЗрддрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдЬреАрд╡рд┐рдд "рдЗрдХрд╛рдИ" рдХреЗ рд╕рдорд╛рди рдкреНрд░рдХрд╛рд░ рд╣реЛрддрд╛ рд╣реИред рдпрд╣ рдХреЛрдб рдХреЗрд╡рд▓ рджреЛ рдЕрдиреБрд░реЛрдз рджреЗрддрд╛ рд╣реИ:


 call next value for hibernate_sequence insert into bank_account (id, /*тАж*/ user_id) values (/*тАж*/) 

рдЬрдм рдПрдХ рдЗрдХрд╛рдИ рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд┐рдпрд╛ рдЬрд╛ рд░рд╣рд╛ рд╣реИ рддреЛ рдХрдИ рдХреНрд╖реЗрддреНрд░реЛрдВ рдореЗрдВ рдПрдХ-рд╕реЗ-рдПрдХ / рдПрдХ-рд╕реЗ-рдПрдХ рд╕рдВрдмрдВрдз рд╣реЛрддреЗ рд╣реИрдВ, рдпрд╣ рддрдХрдиреАрдХ рдбреЗрдЯрд╛рдмреЗрд╕ рдкрд░ рд▓реЛрдб рдХреЛ рдХрдо рдХрд░рдиреЗ рдФрд░ рдХрдо рдХрд░рдиреЗ рдореЗрдВ рдорджрдж рдХрд░реЗрдЧреАред


HQL рдХреНрд╡реЗрд░реА рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдирд╛


рдпрд╣ рдПрдХ рдЕрд▓рдЧ рдФрд░ рджрд┐рд▓рдЪрд╕реНрдк рд╡рд┐рд╖рдп рд╣реИ :)ред рдбреЛрдореЗрди рдореЙрдбрд▓ рд╕рдорд╛рди рд╣реИ рдФрд░ рдЗрд╕ рддрд░рд╣ рдХрд╛ рдЕрдиреБрд░реЛрдз рд╣реИ:


 @Query("select count(ba) " + " from BankAccount ba " + " join ba.user user " + " where user.id = :id") long countUserAccounts(@Param("id") Long id); 

"рд╢реБрджреНрдз" HQL рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ:


 select count(ba) from BankAccount ba join ba.user user where user.id = :id 

рдЬрдм рдЗрд╕реЗ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдирд┐рдореНрди SQL рдХреНрд╡реЗрд░реА рдмрдирд╛рдИ рдЬрд╛рдПрдЧреА:


 select count(ba.id) from bank_account ba inner join user u on ba.user_id = u.id where u.id = ? 

рдПрдХ рдмреБрджреНрдзрд┐рдорд╛рди рдЬреАрд╡рди рдФрд░ рдПрд╕рдХреНрдпреВрдПрд▓ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреА рдЕрдЪреНрдЫреА рд╕рдордЭ рд╕реЗ рднреА рдпрд╣рд╛рдВ рд╕рдорд╕реНрдпрд╛ рддреБрд░рдВрдд рд╕реНрдкрд╖реНрдЯ рдирд╣реАрдВ рд╣реЛрддреА рд╣реИ: рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреБрдВрдЬреА рджреНрд╡рд╛рд░рд╛ inner join user_id рдЦрд╛рддреЛрдВ рдХреЛ рдЧрд╛рдпрдм inner join рд╡рд╛рд▓реЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛_ рдХреЗ рд╕рд╛рде рдЪрдпрди рд╕реЗ рдмрд╛рд╣рд░ рдХрд░ рджреЗрдЧрд╛ (рдФрд░ рдЕрдЪреНрдЫреЗ рддрд░реАрдХреЗ рд╕реЗ, рдЙрдиреНрд╣реЗрдВ рд╕рдореНрдорд┐рд▓рд┐рдд рдХрд░рдирд╛ рд╕реНрдХреАрдорд╛ рд╕реНрддрд░ рдкрд░ рдирд┐рд╖рд┐рджреНрдз рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП, рдЬрд┐рд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ user рддрд╛рд▓рд┐рдХрд╛ рдореЗрдВ рд╢рд╛рдорд┐рд▓ рд╣реЛрдирд╛ рдЖрдо рддреМрд░ рдкрд░ рдирд╣реАрдВ рд╣реИред рдХреА рдЬрд░реВрд░рдд рд╣реИред рдЕрдиреБрд░реЛрдз рдХреЛ рд╕рд░рд▓ (рдФрд░ рддреНрд╡рд░рд┐рдд) рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:


 select count(ba.id) from bank_account ba where ba.user_id = ? 

HQL рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ c рдореЗрдВ рдЗрд╕ рд╡реНрдпрд╡рд╣рд╛рд░ рдХреЛ рдЖрд╕рд╛рдиреА рд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХрд╛ рдПрдХ рддрд░реАрдХрд╛ рд╣реИ:


 @Query("select count(ba) " + " from BankAccount ba " + " where ba.user.id = :id") long countUserAccounts(@Param("id") Long id); 

рдпрд╣ рд╡рд┐рдзрд┐ рдПрдХ "рд▓рд╛рдЗрдЯ" рдЕрдиреБрд░реЛрдз рдмрдирд╛рддреА рд╣реИред


рдХреНрд╡реЗрд░реА рдмрдирд╛рдо рд╡рд┐рдзрд┐ рд╕рд╛рд░


рд╕реНрдкреНрд░рд┐рдВрдЧ рдбреЗрдЯрд╛ рдХреА рдореБрдЦреНрдп рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдореЗрдВ рд╕реЗ рдПрдХ рд╡рд┐рдзрд┐ рдирд╛рдо рд╕реЗ рдПрдХ рдХреНрд╡реЗрд░реА рдмрдирд╛рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рд╣реИ, рдЬреЛ рдмрд╣реБрдд рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИ, рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдЗрдВрдЯреЗрд▓реАрдЬ рдЖрдИрдбреАрдИрдП рд╕реЗ рд╕реНрдорд╛рд░реНрдЯ рдРрдб-рдСрди рдХреЗ рд╕рдВрдпреЛрдЬрди рдореЗрдВред рдкрд┐рдЫрд▓реЗ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ рд╡рд░реНрдгрд┐рдд рдХреНрд╡реЗрд░реА рдХреЛ рдЖрд╕рд╛рдиреА рд╕реЗ рд▓рд┐рдЦрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:


 // @Query("select count(ba) " + " from BankAccount ba " + " where ba.user.id = :id") long countUserAccounts(@Param("id") Long id); // long countByUserAccount_Id(Long id); 

рдпрд╣ рд╕рд░рд▓, рдФрд░ рдЫреЛрдЯрд╛, рдФрд░ рдЕрдзрд┐рдХ рдкрдардиреАрдп, рдФрд░ рд╕рдмрд╕реЗ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдмрд╛рдд рд▓рдЧрддреА рд╣реИ - рдЖрдкрдХреЛ рдЕрдиреБрд░реЛрдз рдХреЛ рд╕реНрд╡рдпрдВ рджреЗрдЦрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред рдореИрдВрдиреЗ рд╡рд┐рдзрд┐ рдХрд╛ рдирд╛рдо рдкрдврд╝рд╛ - рдФрд░ рдпрд╣ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд╕реНрдкрд╖реНрдЯ рд╣реИ рдХрд┐ рдпрд╣ рдХреНрдпрд╛ рдФрд░ рдХреИрд╕реЗ рдЪреБрдирддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рд╢реИрддрд╛рди рдпрд╣рд╛рдБ рд╡рд┐рд╡рд░рдг рдореЗрдВ рд╣реИред @Query рдХреЗ рд╕рд╛рде рдЪрд┐рд╣реНрдирд┐рдд рд╡рд┐рдзрд┐ рдХреЗ рд▓рд┐рдП рдЕрдВрддрд┐рдо рдкреНрд░рд╢реНрди рд╣рдордиреЗ рдкрд╣рд▓реЗ рд╣реА рджреЗрдЦрд╛ рд╣реИред рджреВрд╕рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдХреНрдпрд╛ рд╣реЛрдЧрд╛?


Broads!
 select count(ba.id) from bank_account ba left outer join // <--- !!!!!!! user u on ba.user_id = u.id where u.id = ? 

"рдХреНрдпрд╛ рдмрд╛рдд рд╣реИ!" - рдбреЗрд╡рд▓рдкрд░ рдПрдХреНрд╕рдХреНрд▓реВрд╕рд┐рд╡ рд╣реЛрдЧрд╛ред рдЖрдЦрд┐рд░рдХрд╛рд░, рд╣рдо рдкрд╣рд▓реЗ рд╣реА рджреЗрдЦ рдЪреБрдХреЗ рд╣реИрдВ рд╡рд╛рдпреЛрд▓рд┐рди рдмрд╛рдЬрдиреЗрд╡рд╛рд▓рд╛ join рдЬрд░реВрд░рдд рдирд╣реАрдВ рд╣реИред


рдХрд╛рд░рдг рдЕрднрд┐рдпреБрдХреНрдд рд╣реИ:



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


  • рдПрдХ рдЕрдЪреНрдЫрд╛ рддрд░реАрдХрд╛ optional = false рдЬреЛрдбрд╝рдирд╛ рд╣реИ (рдпрджрд┐ рд╕рд░реНрдХрд┐рдЯ рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ):


     @Entity public class BankAccount { @Id Long id; @ManyToOne @JoinColumn(name = "user_id", optional = false) User user; } 

  • рдмреИрд╕рд╛рдЦреА рддрд░реАрдХрд╛ User рдЗрдХрд╛рдИ рдХреБрдВрдЬреА рдХреЗ рд╕рдорд╛рди рдкреНрд░рдХрд╛рд░ рдХрд╛ рдПрдХ рд╕реНрддрдВрдн рдЬреЛрдбрд╝рдиреЗ рдФрд░ user рдХреНрд╖реЗрддреНрд░ рдХреЗ рдмрдЬрд╛рдп рдкреНрд░рд╢реНрдиреЛрдВ рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣реИ:


     @Entity public class BankAccount { @Id Long id; @ManyToOne @JoinColumn(name = "user_id") User user; @Column(name = "user_id", insertable = false, updatable = false) Long userId; } 

    рдЕрдм рд░рд┐рдХреНрд╡реЗрд╕реНрдЯ-рдлреНрд░реЙрдо-рдореИрдердб рдирд┐рдХреЗрд▓рд░:


     long countByUserId(Long id); 

    рджреЗрддрд╛ рд╣реИ


     select count(ba.id) from bank_account ba where ba.user_id = ? 

    рд╣рдордиреЗ рдХреНрдпрд╛ рд╣рд╛рд╕рд┐рд▓ рдХрд┐рдпрд╛ред



рдирдореВрдирд╛ рд▓реЗрдиреЗ рдХреА рд╕реАрдорд╛


рд╣рдорд╛рд░реЗ рдЙрджреНрджреЗрд╢реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдЪрдпрди рдХреЛ рд╕реАрдорд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╣рдо *RepositoryCustom рд╡рд┐рдзрд┐) рд╕реЗ Optional рд▓реМрдЯрдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ:


 select ba.* from bank_account ba order by ba.rate limit ? 

рдЕрдм рдЬрд╛рд╡рд╛:


 @Override public Optional<BankAccount> findWithHighestRate() { String query = "select b from BankAccount b order by b.rate"; BankAccount account = em .createQuery(query, BankAccount.class) .setFirstResult(0) .setMaxResults(1) .getSingleResult(); return Optional.ofNullable(bankAccount); } 

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


 Caused by: javax.persistence.NoResultException: No entity found for query 

рдЬрд┐рди рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдореЗрдВ рдореИрдВрдиреЗ рджреЗрдЦрд╛, рдЙрдиреНрд╣реЗрдВ рджреЛ рдореБрдЦреНрдп рддрд░реАрдХреЛрдВ рд╕реЗ рд╣рд▓ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛:


  • Optonal.empty() рдЕрдкрд╡рд╛рдж Optonal.empty() рдФрд░ Optonal.empty() рдЙрдиреНрдирдд рд╡рд┐рдзрд┐ рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрдиреБрд░реЛрдз рдХреЗ рд╕рд╛рде рдПрдХ Optonal.empty() рдЧреБрдЬрд░рдиреЗ рдХреА рддрд░рд╣, Optonal.empty() рдФрд░ рдЕрдзрд┐рдХ рдЙрдиреНрдирдд рддрд░реАрдХреЛрдВ рд╕реЗ рд▓реМрдЯрдиреЗ рд╕реЗ рдмрджрд▓рд╛рд╡ рдХреЗ рд╕рд╛рде рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВ
  • рдкрд╣рд▓реВ рдЬрд┐рд╕рдореЗрдВ рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдХреЗ рддрд░реАрдХреЛрдВ рдиреЗ рд▓рд┐рдкрдЯреЗ Optional рд▓реМрдЯрд╛рдпрд╛

рдФрд░ рдмрд╣реБрдд рдХрдо рд╣реА, рдореИрдВрдиреЗ рд╕рд╣реА рд╕рдорд╛рдзрд╛рди рджреЗрдЦрд╛:


 @Override public Optional<BankAccount> findWithHighestRate() { String query = "select b from BankAccount b order by b.rate"; return em.unwrap(Session.class) .createQuery(query, BankAccount.class) .setFirstResult(0) .setMaxResults(1) .uniqueResultOptional(); } 

EntityManager JPA рдорд╛рдирдХ рдХрд╛ рд╣рд┐рд╕реНрд╕рд╛ рд╣реИ, рдЬрдмрдХрд┐ Session рд╣рд╛рдЗрдмрд░рдиреЗрдЯ рдХрд╛ рд╣реИ рдФрд░ IMHO рдПрдХ рдЕрдзрд┐рдХ рдЙрдиреНрдирдд рдЙрдкрдХрд░рдг рд╣реИ, рдЬрд┐рд╕реЗ рдЕрдХреНрд╕рд░ рднреБрд▓рд╛ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред


[рдХрднреА-рдХрднреА] рд╣рд╛рдирд┐рдХрд╛рд░рдХ рд╕реБрдзрд╛рд░


рдЬрдм рдЖрдкрдХреЛ "рдореЛрдЯреА" рдЗрдХрд╛рдИ рд╕реЗ рдПрдХ рдЫреЛрдЯрд╛ рдХреНрд╖реЗрддреНрд░ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рддреЛ рд╣рдо рдпрд╣ рдХрд░рддреЗ рд╣реИрдВ:


 @Query("select a.available from BankAccount a where a.id = :id") boolean findIfAvailable(@Param("id") Long id); 

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


 @Override @Transactional public boolean checkAccount(Long id) { BankAccount acc = repository.findById(id).orElseThow(NPE::new); // ... return repository.findIfAvailable(id); } 

рдпрд╣ рдХреЛрдб рдХрдо рд╕реЗ рдХрдо 2 рдЕрдиреБрд░реЛрдз рдХрд░рддрд╛ рд╣реИ, рд╣рд╛рд▓рд╛рдВрдХрд┐ рджреВрд╕рд░реЗ рдХреЛ рдЯрд╛рд▓рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:


 @Override @Transactional public boolean checkAccount(Long id) { BankAccount acc = repository.findById(id).orElseThow(NPE::new); // ... return repository.findById(id) //    .map(BankAccount::isAvailable) .orElseThrow(IllegalStateException::new); } 

рдирд┐рд╖реНрдХрд░реНрд╖ рд╕рд░рд▓ рд╣реИ: рдкрд╣рд▓реЗ рд╕реНрддрд░ рдХреЗ рдХреИрд╢ рдХреА рдЙрдкреЗрдХреНрд╖рд╛ рди рдХрд░реЗрдВ, рдПрдХ рд▓реЗрдирджреЗрди рдХреЗ рдврд╛рдВрдЪреЗ рдХреЗ рднреАрддрд░, рдХреЗрд╡рд▓ рдкрд╣рд▓рд╛ JpaRepository::findById рдбреЗрдЯрд╛рдмреЗрд╕ рдХреЛ рд╕рдВрджрд░реНрднрд┐рдд рдХрд░рддрд╛ рд╣реИ, JpaRepository::findById рдкрд╣рд▓реЗ рд╕реНрддрд░ рдХрд╛ рдХреИрд╢ рд╣рдореЗрд╢рд╛ рдЪрд╛рд▓реВ рд░рд╣рддрд╛ рд╣реИ рдФрд░ рдПрдХ рд╕рддреНрд░ рд╕реЗ рдмрдВрдзрд╛ рд╣реЛрддрд╛ рд╣реИ, рдЬреЛ рдЖрдорддреМрд░ рдкрд░ рд╡рд░реНрддрдорд╛рди рд▓реЗрдирджреЗрди рд╕реЗ рдмрдВрдзрд╛ рд╣реЛрддрд╛ рд╣реИред


рдЦреЗрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдЯреЗрд╕реНрдЯ (рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдХрд╛ рд▓рд┐рдВрдХ рд▓реЗрдЦ рдХреА рд╢реБрд░реБрдЖрдд рдореЗрдВ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ):


  • рд╕рдВрдХреАрд░реНрдг рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдкрд░реАрдХреНрд╖рдг: InterfaceNarrowingTest
  • рдПрдХ рд╕рдордЧреНрд░ рдХреБрдВрдЬреА рдХреЗ рд╕рд╛рде рдПрдХ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рдкрд░реАрдХреНрд╖рдг рдХрд░реЗрдВ: EntityWithCompositeKeyRepositoryTest
  • рдЕрддрд┐рд░рд┐рдХреНрдд CrudRepository::save рдкрд░реАрдХреНрд╖рдг рдХрд░реЗрдВ CrudRepository::save : ModifierTest.java
  • рдЕрдВрдзрд╛ рдкрд░реАрдХреНрд╖рдг CrudRepository::findById : ChildServiceImplTest
  • рдЕрдирд╛рд╡рд╢реНрдпрдХ left join рдкрд░реАрдХреНрд╖рдг рдореЗрдВ left join : BankAccountControlRepositoryTest

CrudRepository::save рдкрд░ рдПрдХ рдЕрддрд┐рд░рд┐рдХреНрдд рдХреЙрд▓ рдХреА рд▓рд╛рдЧрдд рдХреА рдЧрдгрдирд╛ RedundantSaveBenchmark рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХреА рдЬрд╛ рд╕рдХрддреА рд╣реИред рдЗрд╕реЗ BenchmarkRunner рд╡рд░реНрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд▓реЙрдиреНрдЪ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред

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


All Articles