Atlassianプラグイン:アクティブオブジェクトとプラグイン設定の詳細

こんにちは、Habr! JIRAプラグイン開発部門のMail.Ruグループで働いています。 プラグインを使用すると、アプリケーションの機能を拡張または変更できます。 たとえば、彼らの助けを借りて、新しいタイプのフィールド、ガジェット、JQLクエリ、さまざまな情報を備えたパネル、グラフなどを作成できます。



ほとんどのプラグインでは、使用する追加データのストレージが必要です。 この記事では、この問題をどのように解決するかを説明したいと思います。 このデータを保存する主な方法は、アクティブオブジェクトとプラグイン設定の2つです。 それらをより詳細に検討してみましょう。どちらの場合にどちらを使用するのが良いか、そしてどちらの場合に使用するかがわかります。



画像



1.アクティブなオブジェクト



アクティブオブジェクトは、ORMテクノロジ(オブジェクトリレーショナルマッピング)に基づくライブラリです。 データベースをオブジェクト指向プログラミングの概念に接続し、いわゆる仮想オブジェクトデータベースを作成します。



アクティブオブジェクトは、同様のデータグループを操作するために使用されます。 たとえば、機器、倉庫、請負業者のリストにすることができます。 このような情報は、他のサービスと同期するか、手動で入力できます。 アクティブオブジェクトは、プロジェクト設定、フィールド、およびその他の多くの保存にも適しています。



オブジェクトを作成する



アクティブオブジェクトエンティティを作成するには、net.java.ao.Entityから継承されたインターフェイスを使用します。



public interface Product extends Entity { String getName(); void setName(String name); double getPrice(); void setPrice(double price); }
      
      





ペアのgetメソッドとsetメソッドを使用して、データを受信および書き込みます。 各ペアは、情報が格納されるデータベーステーブルの1つのフィールドを参照します。



アクティブオブジェクトを使用するには、ライブラリをpomファイルに含める必要があります。



 <dependency> <groupId>com.atlassian.activeobjects</groupId> <artifactId>activeobjects-plugin</artifactId> <version>0.23.7</version> <scope>provided</scope> </dependency>
      
      





ActiveObjectsコンポーネントと作成されたすべてのエンティティは、プラグイン構造ファイル(atlassian-plugin.xml)にインポートされます。



 <component-import key="ao" interface="com.atlassian.activeobjects.external.ActiveObjects" /> <ao key="ao-entities"> <entity>com.jira.plugins.shop.model.Product</entity> <entity>com.jira.plugins.shop.model.Shop</entity> </ao>
      
      





アクティブなオブジェクトを操作する



Active Objectsインスタンスを使用するには、別のマネージャークラスを使用すると便利です。 このようなオブジェクトを作成、変更、受信できる関数を集約します。 このクラスを作成した後、それをatlassian-plugin.xmlファイルのコンポーネントとして含めます。



 <component key="product-manager" class="com.jira.plugins.shop.ProductManager" />
      
      





オブジェクトに対するすべての操作は、個別のトランザクションで実行されます。 たとえば、IDでストアを取得するには、次のメソッドを記述できます。



 private final ActiveObjects ao; public Product getProduct(final int id) { return ao.executeInTransaction(new TransactionCallback<Shop>() { @Override public Product doInTransaction() { return ao.get(Product.class, id); } }); }
      
      





多くの場合、さまざまなデータサンプルを受信する必要があります。 net.java.ao.Query



クラスを使用して、任意のSQLクエリを作成できます。 確かに、データベースからのフィールドの名前に縛られるため、これを行うことは望ましくありません。



 public Product[] getProducts(final String name) { return ao.executeInTransaction(new TransactionCallback<Product[]>() { @Override public Product[] doInTransaction() { return ao.find(Product.class, Query.select().where("NAME = ?", name).order("NAME")); } }); }
      
      





Active Objectsインスタンスは、 ao.create



関数を使用して作成されます。 次に、必要に応じて、そのフィールドが埋められます。 重要な注意:オブジェクトは編集後に保存する必要があります。そうしないと、すべての変更が失われます。



 public Product createProduct(final String name, final double price) { return ao.executeInTransaction(new TransactionCallback<Product>() { @Override public Product doInTransaction() { Product product = ao.create(Product.class); product.setName(name); product.setPrice(price); product.save(); return product; } }); }
      
      





変更する場合、最初にデータベースからオブジェクトを取得してから、その内容を変更する必要があります。



インスタンス自体が渡されるao.delete



を使用して削除が行われます。



 public void deleteProduct(final int id) { ao.executeInTransaction(new TransactionCallback<Void>() { @Override public Void doInTransaction() { Product product = ao.get(Product.class, id); ao.delete(product); return null; } }); }
      
      





場合によっては、オブジェクトを完全に削除するのではなく、たとえばdeleted



フィールドで削除済みとしてマークする方が良い場合があります



オブジェクト間のリンク



アクティブなオブジェクトは互いに関連付けることができます。 接続には3つのタイプがあります。 それぞれについて詳しく説明します。



一対一のコミュニケーション



たとえば、ストアは1つのアドレスのみを持つことができ、したがって、ネットワークからの1つのストアは1つのアドレスを持つことができます。



 public interface Shop extends Entity { @OneToOne Address getAddress(); } public interface Address extends Entity { Shop getShop(); void setShop(Shop shop); }
      
      





オブジェクトをリンクするには、 setShop(Shop shop)



呼び出す必要があります。



1対多の関係



たとえば、店舗には複数の売り手がいる場合がありますが、売り手は1つの店でしか働きません。



 public interface Shop extends Entity { @OneToMany Seller[] getSellers(); } public interface Seller extends Entity { Shop getShop(); void setShop(Shop shop); }
      
      





多対多の関係



たとえば、製品がネットワーク内の異なる店舗にある場合や、店舗に多くの製品がある場合があります。 したがって、この関係はProduct



クラスとShop



クラスに適用されます。 他の2つをリンクする3番目のエンティティを作成する必要があります(リレーショナルデータベースの追加テーブルとして)。



注釈はgetメソッドにのみ設定されます。



 public interface Shop extends Entity { @ManyToMany(value = ProductToShop.class) Product[] getProducts(); } public interface Product extends Entity { @ManyToMany(value = ProductToShop.class) Shop[] getShops(); } public interface ProductToShop extends Entity { Product getProduct(); void setProduct(Product product); Shop getShop(); void setShop(Shop shop); }
      
      





データ保存



アクティブオブジェクトは別のデータベーステーブルに保存されます。 デフォルトでは、テーブル名は3つの部分で構成されています。 最初は、AO(アクティブオブジェクト)プレフィックスで構成されます。 2番目は、プラグインキーのMD5ハッシュの6文字の16進値、または存在する場合はアクティブオブジェクトモジュールのnamespace



属性です。 最後の部分は、Active Objectsエンティティの名前です。 標準名の例は次のようになります: AO_28BE2D_MY_OBJECT







テーブルの列名は、データベースから値を挿入および取得することによって決定されます。 大文字の名前はアンダースコアで区切られます。 たとえば、メソッドの名前がgetProductId()



場合、列の名前はPRODUCT_ID



ます。



アクティブオブジェクトは、次のデータタイプで機能します。





テーブルと列の名前を変更する



データベースでは名前の長さに制限があるため、名前の変更はコードのリファクタリングおよび長いフィールド名に使用されます。



デフォルトのテーブル名を変更するには、 @Table("NewName")



アノテーションを使用する必要があります。



 @Table("Item") public interface Product extends Entity { double getPrice(); void getPrice(double price); }
      
      





フィールドの名前を変更するときは、 @Mutator("NewName")



および@Accessor("NewName")



注釈が必要です。 ただし、テーブル自体の列名は変更されません。 アノテーション@Accessor



、値を返す関数に対して指定され、 @Accessor



値を変更する関数に対して指定されます。



 public interface Product extends Entity { @Accessor("Cost") double getPrice(); @Mutator("Cost") void getPrice(double price); }
      
      





落とし穴



現在、アクティブオブジェクトはBLOB



データ型では機能しません。 この場合、情報はファイルシステムに直接保存できます。



関係にも問題があります。 例で説明しましょう。 アドレスとストアの2つのエンティティがあります。 それらの間には1対1の関係が確立されます。 都市の名前を変更してみましょう。 住所から店舗オブジェクトをリクエストし、住所から住所オブジェクトをリクエストすると、古いバージョンでは都市の値が返されます。 実際、オブジェクトを変更するときのフィールドは再び初期化されません。 この場合、オブジェクトに他のオブジェクトへのリンクがある場合、変更後に再度初期化する必要があります。



データベースでの作成および検索操作では、列名の大文字と小文字が区別される場合があります。 また、長さは30文字を超えることはできず、予約語BLOB



CLOB



NUMBER



ROWID



TIMESTAMP



VARCHAR2



使用できません。



オブジェクトに長いテキストフィールドが必要な場合、アノテーション@StringLength(StringLength.UNLIMITED)



がその前に配置されます。 たとえば、MySQLでは、通常の文字列の長さは255文字です。



2.プラグイン設定



プラグイン設定は、Atlassianフレームワークの共有アクセスレイヤーの一部です。 これらは、キーと値のペアの形式でデータストレージを提供し、プラグインは操作中にこれを参照します。



プラグインの一般的な設定を保存する必要がある場合があります。 同時に、1つのレコードに対して個別のテーブルを開始することは実用的ではありません。 このような場合、プラグイン設定を使用すると便利です。



設定の作成と使用



プラグイン設定オブジェクトを作成するには、 PluginSettingsFactory



インターフェイスを使用する必要があります。 Key-Valueの形式で設定を作成できます。 重要:キーは一意である必要があるため、プラグインのフルネームを取得できます。 プラグイン設定の使用例は次のとおりです。



 public interface PluginData { String getDistributingFacilitiesName(); void setDistributingFacilitiesName(String distributingFacilitiesName); } public class PluginDataImpl implements PluginData { private static final String PLUGIN_PREFIX = "com.jira.plugins.shop:"; private static final String DISTRIBUTING_FACILITIES_NAME = PLUGIN_PREFIX + "distributingFacilitiesName"; private final PluginSettingsFactory pluginSettingsFactory; public PluginDataImpl(PluginSettingsFactory pluginSettingsFactory) { this.pluginSettingsFactory = pluginSettingsFactory; } @Override public String getDistributingFacilities() { return (String) pluginSettingsFactory.createGlobalSettings().get(DISTRIBUTING_FACILITIES_NAME); } @Override public void getDistributingFacilities(String distributingFacilitiesName) { pluginSettingsFactory.createGlobalSettings().put(DISTRIBUTING_FACILITIES_NAME, distributingFacilitiesName); } }
      
      





プロジェクトのグローバル設定とローカル設定の両方を作成できます。





データ保存



情報はデータベースのテーブルに保存されます。 propertyentry



テーブルには、プラグイン設定の名前、キー、および値のタイプが記録されます。 プロパティの値は、そのタイプに対応するテーブル、たとえばpropertystring



書き込まれpropertystring



。 プラグイン設定でサポートされるデータ型:





落とし穴



さまざまなクラスでプラグイン設定を使用するには、操作ごとにオブジェクトを作成する必要があります。 実際には、オブジェクトを作成するときに、一度初期化されます。 他の場所で変更された場合、現在のクラスではこれらの変更は表示されません。



オブジェクトの1つのプロパティに値のリストなどのビッグデータを格納することは、悪いスタイルと見なされます。 このリストから1つのアイテムにアクセスするには、そのアイテム全体を初期化する必要があります。 同じ設定の場合、 COLOR_1



COLOR_2



などの形式のキーを作成する必要があります。それらが関連していることを忘れて、簡単に混乱する可能性があります。



名前を変更することができ、キーは常に変更されておらず一意であるため、ユーザーを保存するときは、名前(名前)ではなく、キー(キー)を記録する必要があることに注意してください。



おわりに



プラグインにデータを保存する2つの方法を検討しました。 単一構成の場合、プラグイン設定が適しています。 キーと値の形式の構造により、必要な設定をすばやく取得できます。 プラグイン設定を使用して、ローカル構成とグローバル構成の両方を作成できます。



機器のリスト、請負業者など、同じタイプの大きなデータセットの場合、アクティブオブジェクトを使用することをお勧めします。

アトラシアンによると、これらは情報を保存およびアクセスするためのシンプルで高速かつスケーラブルな方法です。 データはデータベース内の別のテーブルに保存されます。 オブジェクトは互いにリンクできます。



使用されたソース:



  1. アトラシアンアクティブオブジェクトのドキュメント
  2. アクティブオブジェクトプラグインの概要
  3. アトラシアンプラグイン設定のドキュメント
  4. プラグイン設定を保存する方法と場所


PSソーシャルネットワークにはプロのコミュニティがあり、アトラシアン製品の使用について話し合ったり、経験を共有したり、ライブミーティングを手配したりしています。 プラグインを作成して結果を共有してください! 参加:






All Articles