jira ao UpgradeTask

插件发布到市场后,后续版本迭代的过程中,可能会对ao实体类的字段作添加或删除,或者要将某一字段的值映射解析到另一字段上。

本来这个工作,可以在插件启动的时候,在实现了com.atlassian.sal.api.lifecycle.LifecycleAware 接口的类onStart方法类完成。

但是历史版本更新了哪些字段不好维护,以前查看其它插件的代码时有看到版本更新任务的代码,但是因为实际工作中用的很少,就没去细看。

这几天查看atlassian的文档时,发现有一篇专门介绍如何处理upgradTask的文档。其实这篇文档是在一个系列中的,话说回来,atlassian插件开发的文档虽然挺全的,但是总体的文档结构还是有点乱的。

官网链接:处理AO升级任务

下文是对文档上的一些内容的截取


 

比如说我们之前有一个Todo类,它继承了Entity

 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表,用来存放用户信息。

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字段被移除

上一篇:基于酷Q的工作秘书机器人


下一篇:JIRA 7.8 版本的安装与破解