春のペットクリニックをきっかけに。 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を準備します。

ご清聴ありがとうございました。取り上げられたトピックについてご意見をお聞かせください。



All Articles