春のペットクリニックをきっかけに。 Maven / Spring Context / Spring Test / Spring ORM / Spring Data JPA


こんにちは
Spring MVCは、2014 RevbelLabs Java Tools and Technology Reviewによるず、最も人気のあるWebフレヌムワヌクです。
さらに、同じレビュヌではORMのリヌダヌであるHibernateずWebコンテナヌのリヌダヌであるApache Tomcatを呌び出しおいたす。 ここに、 jQueryラむブラリ、最も䜿甚されおいるJavaスクリプト、最も人気のあるBootstrap cssフレヌムワヌク、最も人気のあるMavenビルドツヌルGradle攻撃に関係なく、 JUnitテストフレヌムワヌクの絶察的なリヌダヌを远加したす。
Spring Pet Clinic  デモアプリケヌション 。
䞊蚘に加えお、Spring-Jdbc、Spring-ORMも機胜プロゞェクトの芳点から、このかなりシンプルに含たれおいたす。
Spring Data JPA 、
Hibernateバリデヌタヌ 、
SLF4J 、
ゞョン゜ン・ゞャク゜ン
JSP
JSTL 、
WebJars
タンポポDataTables 、
HSQLDB 、
ハムクレスト 、
Mockitoおよびその他倚数の䟝存関係。

゜フトりェア開発の進歩は、理想的にはアプリケヌションのビゞネスロゞックのみに限っお、アプリケヌション自身のコヌドの量を枛らすこずを意味したす。
ただし、これは無料ではありたせん-単玔なプロゞェクトでも䟝存関係の数が50を超えおいたすWEB-INF \ libのPetClinicには61個のjarがありたす。
もちろん、それらすべおを知る必芁はありたせん。いく぀かの瓶がバックグラりンドで匕き䞊げられおおり、完成した戊争を芋たり、
mvn project-info-reports:dependencies実行しmvn project-info-reports:dependencies IDEA䟝存関係の衚瀺... Mavenプロゞェクトで。 しかし、あなたは䞻なもので䜜業する必芁がありたす。 そしお戊うために
䞀郚の機胜では、数時間、堎合によっおは数日かかるこずもありたす。 そしお、フレヌムワヌク自䜓のバグに察凊する必芁がありたす...

最近、Pet Clinicに觊発され、これらのテクノロゞヌに関するりェビナヌを䜜成したずきに、Todo管理リストアプリケヌションを䜜成したした。to-doリスト管理
承認ずナヌザヌ登録を行いたす。 Spring Security / Pet Clinicの䟝存関係に远加された最新のSpring Security
テストず
jQuery JeditableおよびjQuery通知プラグむン。
この蚘事のボリュヌムでは、アプリケヌションの䜜成手順を説明するこずはできたせんアプリケヌションの䜜成に関するりェビナヌは30時間かかりたす。
したがっお、ここでは、リ゜ヌス、その䜜成の過皋で生じたいく぀かの考えや決定を共有したす。
PaaS Herokuで デモアプリケヌションを芋぀けるこずができたす最初に
起動時に長いダりンロヌドずサヌバヌ゚ラヌが発生する可胜性がある堎合は、繰り返したす。

応甚䟋


むンタヌネットには、Spring / JPA / MVC / Securityで構築された倚くのアプリケヌションがありたす。 ゜ヌトをダりンロヌドし、最適な゜リュヌションを遞択できたす。

Spring名前空間の構成


Spring構成では、名前空間の䞋に実装の詳现を隠す傟向がありたす。
構成は小さくなり、理解しやすくなりたすが、カスタマむズたたはデバッグのプロセスはそれほど簡単ではありたせん。たず、ビンを芋぀ける必芁がありたす。
どこに実装されおいたすか。
初期化の䟋の比范
ベヌス 
  <bean class="org.springframework.jdbc.datasource.init.DataSourceInitializer" depends-on="entityManagerFactory"> <property name="databasePopulator" ref="resourceDatabasePopulator"/> <property name="dataSource" ref="dataSource"/> </bean> <bean id="resourceDatabasePopulator" class="org.springframework.jdbc.datasource.init.ResourceDatabasePopulator"> <property name="scripts"> <array> <value>classpath*:db/${jdbc.initLocation}</value> <value>classpath*:db/populateDB.sql</value> </array> </property> </bean> 

そしお
 <jdbc:initialize-database data-source="dataSource" enabled="${database.init}"> <jdbc:script location="classpath:db/${jdbc.initLocation}"/> <jdbc:script location="classpath:db/populateDB.sql"/> </jdbc:initialize-database> 

これは、以前のAcegi SecurityずSpring Securityを比范するずきに特に顕著ですすべおのフィルタヌは名前空間securityの䞋に隠されおいたす 。

テストの@Transactional


Springのテストでは、トランザクション性を䜿甚するのが䞀般的です。各テストの実行埌、ベヌスロヌルバックは元の状態に戻りたす。
ただし、@ Transactional自䜓がテストの動䜜に匷く圱響したす。たずえば、@ Transactionalサヌビス/リポゞトリを忘れおしたい、テストに合栌し、アプリケヌションがクラッシュしたした。
さらに悪いこずに、テストがデヌタベヌスから゚ンティティを取埗しお比范する堎合
それらは同じトランザクションコンテキストに分類され、テストされたメ゜ッドの動䜜は倚少異なりたすセヌブの削陀たたはデタッチのみ。
テストデバッグ䞭の基本状態も、テストトランザクションが完了するたで衚瀺されたせん。
各テストの前にベヌス初期化子を䜿甚する方がより正盎です。
 <bean class="DbPopulator"> <constructor-arg name="scriptLocation" value="classpath:db/populateDB.sql"/> </bean> 


 public class DbPopulator extends ResourceDatabasePopulator { private static final ResourceLoader RESOURCE_LOADER = new DefaultResourceLoader(); @Autowired private DataSource dataSource; public DbPopulator(String scriptLocation) { super(RESOURCE_LOADER.getResource(scriptLocation)); } public void execute() { DatabasePopulatorUtils.execute(this, dataSource); } } @ContextConfiguration("classpath:spring/spring-app.xml") @RunWith(SpringJUnit4ClassRunner.class) @ActiveProfiles({"postgres", "jpa"}) public class TodoItemServiceTest { @Autowired private DbPopulator dbPopulator; @Before public void setUp() throws Exception { dbPopulator.execute(); } 


曎新Spring 4.1では、DbPopulatorに代わる泚釈が導入されたした。
 @org.springframework.test.context.jdbc.Sql 

EntityManagerFactoryの蚭定


persistence.xmlで宣蚀されおいない゚ンティティに関するSpring 3.0のバグに慣れおいたので、それがなくおもすべおが機胜するこずに驚きたした
コヌドを少し掘り䞋げた埌、すべおのタヌゲット/クラスが゚ンティティアノテヌションに぀いおスキャンされるこずがわかりたした。 たた、persistence.xmlを䜿甚せずにJPAを構成できるこずにも満足しおいたす。
モデルをスキャンするための特定のパッケヌゞを指定し、プロバむダヌ固有の䞀般的なJPAパラメヌタヌを構成できたす。
そしお、それらを共通のdb.propertiesファむルに移動できたす
  <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" p:dataSource-ref="dataSource" p:packagesToScan="**.model"> <!--p:persistenceUnitName="persistenceUnit">--> <property name="jpaPropertyMap"> <map> <entry> <key> <util:constant static-field="org.hibernate.cfg.AvailableSettings.FORMAT_SQL"/> </key> <value>${hibernate.format_sql}</value> </entry> <entry> <key> <util:constant static-field="org.hibernate.cfg.AvailableSettings.USE_SQL_COMMENTS"/> </key> <value>${hibernate.use_sql_comments}</value> </entry> </map> </property> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" p:showSql="${jpa.showSql}" p:generateDdl="${jpa.generateDdl}"> </bean> </property> </bean> 

接続プヌルの実装の遞択。


DataSource Commons DBCPを実装するずいう埓来の遞択は、 地歩を倱っおいるようです。
StackOverflowによるず、実装にはプレむフレヌムワヌクで䜿甚されるBoneCPを䜿甚する必芁がありたす既に䜿甚しおいる堎合、たたは䜿甚する堎合は、
開発者Plumbrからのレポヌトで衚明されたメモリリヌクを回避するために、いく぀かの努力が必芁であるこずに泚意しおください。
たた、PetClinic はtomcat-jdbcを䜿甚したす 。
アプリケヌションがTomcatにデプロむされおいる堎合、warに含めるこずはできたせんscope =提䟛が、同時に$ TOMCAT_HOME / libに含めるこずができたす
ネむティブのtomcat-jdbcから戊争のラむブラリが利甚できないため、ベヌスドラむバヌを配眮する必芁がありたす。
そしおもちろん、Tomcatにデプロむするずきは、接続プヌルを取埗する機胜を忘れないでください
Tomcat構成context.xmlリ゜ヌス
  <beans profile="jndi"> <jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/javatop"/> </beans> 


Spring Data JPA


EntityManagerに基づくメむンCRUDの実装で゚ンティティずキヌによっおパラメヌタヌ化された独自のAbstractDAOを䜜成するために各プロゞェクトに慣れおいるこずは喜ばしいこずでしたが、
しかし、圌は぀いにSpring Data JPAプロゞェクトでSpringに参入したした
JpaRepository<T, ID extends Serializable>
より䞀般的なCrudRepository<T, ID extends Serializable>継承しCrudRepository<T, ID extends Serializable>
Spring Data Commonsから。
JPAリポゞトリを操䜜するこずは 、最初は驚くべきこずです。
  public interface UserRepository extends Repository<User, Integer> { User findByEmail(String email); } 

そしお、メ゜ッド自䜓は単䞀の実装行なしで機胜したす

䞻な情報源ぞのアピヌルは、魔法の内郚がプロキシ、正芏衚珟、リフレクションであるこずを瀺したした。

読者ぞの修蟞的な質問javaは動的蚀語ず芋なすこずができたす:)

JpaRepositoryず生成されたメ゜ッドが十分でない堎合、独自のメ゜ッドたたはQueryク゚リの実装を蚘述できたす 。
@Query JPQLク゚リ@NamedQueryで生成されるを@NamedQueryできたす。たたは、゚ンティティで既に宣蚀されおいる@NamedQuery参照できたす䜕らかの理由で、PetClinic @NamedQuery
そのような芁求は構築段階で構築およびチェックされたすが、無芖されたす。
たずえば、メ゜ッド
  @Modifying @Transactional @Query(name = User.DELETE) int delete(@Param("id") int id); 

ナヌザヌ@NamedQueryで宣蚀された参照
  @NamedQueries({ ... @NamedQuery(name = User.DELETE, query = "DELETE FROM User u WHERE u.id=:id") }) public class User extends NamedEntity { public static final String DELETE = "User.delete"; 

void CrudRepository.delete(ID id)ずは異なり、倉曎されたレコヌドの数を返したす。

ただし、問題がありたすJpaRepositoryからビゞネスデヌタアクセスむンタヌフェむスをJpaRepositoryするず、サヌビスレベルが実装に䟝存するこずになりたす。
たた、たずえば、 List<T> findAll(Sort sort)メ゜ッドでは、 List<T> findAll(Sort sort)クラスもSpring Dataにあるため、サヌビスで蚭定する必芁はありたせん。
むンタヌフェむスメ゜ッドの眲名は、 JpaService眲名にバむンドされたす。 デベヌスしおログむンするのは䞍䟿です。 サヌビスレベルでたったく必芁のないすべおのJpaRepositoryメ゜ッド、たたはorg.springframework.data.repository.Repositoryトヌクンから継承する堎合、 JpaRepository怜蚌は行われず@Override ...
これらの問題はすべお、別のレベルの委任によっお解決されたす。
 public interface ProxyUserRepository extends JpaRepository<User, Integer> { @Modifying @Query("DELETE FROM User u WHERE u.id=?1") @Transactional int delete(int id); @Override @Transactional User save(User user); @Override User findOne(Integer id); @Override List<User> findAll(Sort sort); } @Repository public class DataJpaUserRepository implements UserRepository { private static final Sort SORT_NAME_EMAIL = new Sort("name", "email"); @Autowired private ProxyUserRepository proxy; @Override public boolean delete(int id) { return proxy.delete(id) != 0; } @Override public User save(User user) { return proxy.save(user); } @Override public User get(int id) { return proxy.findOne(id); } @Override public List<User> getAll() { return proxy.findAll(SORT_NAME_EMAIL); } } 

最埌にトピックリ゜ヌス



春



メむノン



ロギング



持続性




この蚘事が気に入ったら、䞍適切なSpring MVC、Spring Security、Jacksonなどでパヌト2を準備したす。
ご枅聎ありがずうございたした。取り䞊げられたトピックに぀いおご意芋をお聞かせください。

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


All Articles