插件發佈到市場後,後續版本迭代的過程當中,可能會對ao實體類的字段做添加或刪除,或者要將某一字段的值映射解析到另外一字段上。java
原本這個工做,能夠在插件啓動的時候,在實現了com.atlassian.sal.api.lifecycle.LifecycleAware 接口的類onStart方法類完成。sql
可是歷史版本更新了哪些字段很差維護,之前查看其它插件的代碼時有看到版本更新任務的代碼,可是由於實際工做中用的不多,就沒去細看。數據庫
這幾天查看atlassian的文檔時,發現有一篇專門介紹如何處理upgradTask的文檔。其實這篇文檔是在一個系列中的,話說回來,atlassian插件開發的文檔雖然挺全的,可是整體的文檔結構仍是有點亂的。api
官網連接:處理AO升級任務ide
下文是對文檔上的一些內容的截取this
好比說咱們以前有一個Todo類,它繼承了Entitygoogle
1 @Preload 2 public interface Todo extend Entity { 3 void setUserName (String userName ); 4 5 String getUserName (); 6 7 String getDescription (); 8 9 void setDescription (String description ); 10 11 boolean isComplete (); 12 13 void setComplete (boolean complete ); 14 }
Todo類中維護了一個userName字段,可是在後續的開發中,用戶須要維護的信息不少,不止是用戶名這麼簡單了。此時咱們須要從新建一個User表,用來存放用戶信息。spa
1 public interface User extends Entity 2 { 3 String getName(); 4 void setName(String name); 5 }
Todo類也得作修改插件
1 package com.atlassian.tutorial.ao.todo; 2 3 import net.java.ao.Entity; 4 import net.java.ao.Preload; 5 import net.java.ao.schema.NotNull; 6 7 @Preload 8 public interface Todo extends Entity 9 { 10 @NotNull 11 void setUser(User user); 12 13 @NotNull 14 User getUser(); 15 16 String getDescription(); 17 18 void setDescription(String description); 19 20 boolean isComplete(); 21 22 void setComplete(boolean complete); 23 } 24
以前service裏的方法固然得修改,但這不是咱們這裏討論的重點,接下來咱們看,如何使用upgradetask更新數據庫數據。日誌
首先在ao包下面新建一個pacakge,名爲upgrade.v2(官網上還建了v1包,可是那個升級改動較小,這裏就不詳述了)。
每次版本更新都要新建一個(v版本號)的包,包內存放須要更新的數據庫實體類(從ao.entity包內複製過來,並作相應的改動。它不會在數據庫內從新建一張表,只是用來記錄更新信息)和更新任務類
1 package com.atlassian.tutorial.ao.todo.upgrade.v2; 2 3 import net.java.ao.Entity; 4 import net.java.ao.Preload; 5 // 保留了須要更新掉的字段user_name和須要新增的user_id字段(即getUser) 6 @Preload 7 public interface Todo extends Entity 8 { 9 void setUserName(String userName); 10 11 String getUserName(); 12 13 void setUser(User user); 14 15 User getUser(); 16 17 String getDescription(); 18 19 void setDescription(String description); 20 21 boolean isComplete(); 22 23 void setComplete(boolean complete); 24 }
user表是新增的,沒有改動,直接複製過來
接下來就是更新的代碼類了
1 package com.atlassian.tutorial.ao.todo.upgrade.v2; // (1) 引用upgrade.v2包下的類 2 3 import com.atlassian.activeobjects.external.ActiveObjects; 4 import com.atlassian.activeobjects.external.ActiveObjectsUpgradeTask; 5 import com.atlassian.activeobjects.external.ModelVersion; 6 import com.google.common.collect.ImmutableMap; 7 import net.java.ao.Query; 8 9 public final class TodoUpgradeTask002 implements ActiveObjectsUpgradeTask 10 { 11 @Override 12 public ModelVersion getModelVersion() 13 { 14 return ModelVersion.valueOf("2"); // (2) 版本設置爲2 15 } 16 17 @Override 18 public void upgrade(ModelVersion currentVersion, ActiveObjects ao) 19 { 20 ao.migrate(Todo.class, User.class); // (3) 聲明須要操做的類 21 22 Todo[] todos = ao.find(Todo.class); // (4) 實際升級,設置User對應的userName。 23 for (Todo todo : todos) 24 { 25 todo.setUser(getOrCreateUser(ao, todo.getUserName())); 26 todo.save(); 27 } 28 } 29 30 private User getOrCreateUser(ActiveObjects ao, String userName) 31 { 32 User[] users = ao.find(User.class, Query.select().where("NAME = ?", userName)); 33 if (users.length == 0) { 34 return createUser(ao, userName); 35 } else if (users.length == 1) { 36 return users[0]; 37 } else { 38 throw new IllegalStateException("There shouldn't be 2 users with the same username! " + userName); 39 } 40 } 41 42 private User createUser(ActiveObjects ao, String userName) 43 { 44 return ao.create(User.class, ImmutableMap.<String, Object>of("NAME", userName)); 45 } 46 }
最後,須要在atlassian-plugin.xml中配置
1 <ao key="ao-module"> 2 <description>The module configuring the Active Objects service used by this plugin</description> 3 <entity>com.atlassian.tutorial.ao.todo.Todo</entity> 4 <entity>com.atlassian.tutorial.ao.todo.User</entity> 5 <upgradeTask>com.atlassian.tutorial.ao.todo.upgrade.v1.TodoUpgradeTask001</upgradeTask> 6 <upgradeTask>com.atlassian.tutorial.ao.todo.upgrade.v2.TodoUpgradeTask002</upgradeTask> 7 </ao>
執行,下面是官網給出的執行日誌,
1 [INFO] [talledLocalContainer] INFO - assian.activeobjects.internal.ActiveObjectUpgradeManagerImpl - Starting upgrade of data model, current version is 1 2 [INFO] [talledLocalContainer] DEBUG - net.java.ao.sql - CREATE TABLE AO_3F7D93_USER ( 3 [INFO] [talledLocalContainer] ID INTEGER GENERATED BY DEFAULT AS IDENTITY (START WITH 1) NOT NULL, 4 [INFO] [talledLocalContainer] NAME VARCHAR(255), 5 [INFO] [talledLocalContainer] PRIMARY KEY(ID) 6 [INFO] [talledLocalContainer] ) 7 [INFO] [talledLocalContainer] DEBUG - net.java.ao.sql - ALTER TABLE AO_3F7D93_TODO ADD COLUMN USER_ID INTEGER 8 [INFO] [talledLocalContainer] DEBUG - net.java.ao.sql - ALTER TABLE AO_3F7D93_TODO ADD CONSTRAINT fk_ao_3f7d93_todo_user_id FOREIGN KEY (USER_ID) REFERENCES AO_3F7D93_USER(ID) 9 [INFO] [talledLocalContainer] DEBUG - net.java.ao.sql - CREATE INDEX index_ao_3f7d93_todo_user_id ON AO_3F7D93_TODO(USER_ID) 10 [INFO] [talledLocalContainer] DEBUG - net.java.ao.sql - SELECT * FROM AO_3F7D93_TODO 11 [INFO] [talledLocalContainer] DEBUG - net.java.ao.sql - SELECT ID FROM AO_3F7D93_USER WHERE NAME = ? 12 [INFO] [talledLocalContainer] DEBUG - net.java.ao.sql - INSERT INTO AO_3F7D93_USER (NAME) VALUES (?) 13 [INFO] [talledLocalContainer] DEBUG - net.java.ao.sql - UPDATE AO_3F7D93_TODO SET USER_ID = ? WHERE ID = ? 14 [INFO] [talledLocalContainer] DEBUG - net.java.ao.sql - SELECT ID FROM AO_3F7D93_USER WHERE NAME = ? 15 [INFO] [talledLocalContainer] DEBUG - net.java.ao.sql - UPDATE AO_3F7D93_TODO SET USER_ID = ? WHERE ID = ? 16 [INFO] [talledLocalContainer] DEBUG - net.java.ao.sql - SELECT ID FROM AO_3F7D93_USER WHERE NAME = ? 17 [INFO] [talledLocalContainer] DEBUG - net.java.ao.sql - INSERT INTO AO_3F7D93_USER (NAME) VALUES (?) 18 [INFO] [talledLocalContainer] DEBUG - net.java.ao.sql - UPDATE AO_3F7D93_TODO SET USER_ID = ? WHERE ID = ? 19 [INFO] [talledLocalContainer] DEBUG - net.java.ao.sql - SELECT ID FROM AO_3F7D93_USER WHERE NAME = ? 20 [INFO] [talledLocalContainer] DEBUG - net.java.ao.sql - UPDATE AO_3F7D93_TODO SET USER_ID = ? WHERE ID = ? 21 [INFO] [talledLocalContainer] INFO - assian.activeobjects.internal.ActiveObjectUpgradeManagerImpl - Finished upgrading, model is up to date at version 2 22 [INFO] [talledLocalContainer] DEBUG - net.java.ao.sql - ALTER TABLE AO_3F7D93_TODO DROP COLUMN USER_NAME 23 [INFO] [talledLocalContainer] DEBUG - net.java.ao.sql - ALTER TABLE AO_3F7D93_TODO DROP CONSTRAINT fk_ao_3f7d93_todo_user_id 24 [INFO] [talledLocalContainer] DEBUG - net.java.ao.sql - ALTER TABLE AO_3F7D93_TODO ALTER COLUMN USER_ID INTEGER NOT NULL 25 [INFO] [talledLocalContainer] DEBUG - net.java.ao.sql - ALTER TABLE AO_3F7D93_TODO ADD CONSTRAINT fk_ao_3f7d93_todo_user_id FOREIGN KEY (USER_ID) REFERENCES AO_3F7D93_USER(ID)
最後幾行能夠看出,在完成升級任務以後,數據庫的表結構也變了,user_name字段被移除