2012-05-29 37 views
0

我处于有100个表(实体类)和100个屏幕(每个为1个)的情况。让我们看看2个屏幕:ShipviaTopComponent和RouteTopComponent。 RouteTopComponent有以下方法:提取实体保存类

public static void saveRecord() { 
    Route r = resultList.get(currentPos); 
    EntityManager entityManager = Persistence.createEntityManagerFactory("EntityLibraryPU").createEntityManager(); 
    entityManager.getTransaction().begin(); 
    r = entityManager.find(Route.class, r.getRouteKey()); 
    r.setRoute(txtRoute.getText());; 
    entityManager.persist(r); 
    entityManager.getTransaction().commit(); 
} 

现在,如果我把每一个100米的屏幕的那种方法,这样就可以了;但是我正在考虑将它提取到它自己的类中。这意味着它不总是路由,但可以是Shipvia或任何其他实体类。

我期待着我的RouteTopComponent调用它,如下所示:

com.demo.viewer.SaveRecord.SaveRecord(r); 

这个r包含了我所需要的一切。这是SaveRecord类。

public class SaveRecord { 

public static void saveRecord(entity.Route r) { 

    EntityManager entityManager = Persistence.createEntityManagerFactory("EntityLibraryPU").createEntityManager(); 
    entityManager.getTransaction().begin(); 
    r = entityManager.find(Route.class, r.getRouteKey()); 
    r.setRoute("01-banana"); //Hardcode this for now 
    entityManager.persist(r); 
    entityManager.getTransaction().commit(); 
} 

一个我有问题 - 它期待entity.Route如果我通过“R”给它。但是如果我通过Shipvia,它将会破裂。有什么办法可以让我期待像entity.Anything

编辑:根据建议,我试图创建一个超类实体。

超类AddChg实体 - http://pastebin.com/1iW67NVn

SHIPVIA实体 - http://pastebin.com/R53tNHyp(只是原来,正常的实体)

路线实体 - http://pastebin.com/5DCvj340(扩展AddChg)

的一块为SaveRecord代码(我把它命名为SaveResult)看起来像这样:

public static <T extends AddChg> void SaveResult(T r) { 
    EntityManager entityManager = Persistence.createEntityManagerFactory(
     "EntityLibraryPU").createEntityManager(); 
     entityManager.getTransaction().begin(); 
     r = entityManager.find(Route.class, r.getId()); 
     r.setSomething("01-banana"); 
     entityManager.persist(r); 
     entityManager.getTransaction().commit(); 
} 

现在,它似乎工作,在一个感觉当r。拉扯超类的所有内容。只有一行似乎给我带来麻烦:

 r = entityManager.find(Route.class, r.getId()); 

Route.class也必须根据试图访问哪个实体而有所不同。并且r.getId()必须是正在保存的实体的PK。

因此,例如,如果用户想编辑RouteTop屏幕,该行应读取;

r = entityManager.find(Route.class, r.getRouteKey()); 

但是对于ShipviaTopScreen它将是;

r = entityManager.find(Shipvia.class, r.getShipvViaCd()); 

我能够通过这些作为参数,如:

public static <T extends AddChg> void SaveResult(T r, Class c, String PK) 

EDIT3:上述工程的解决方案,最后我还有最后一个问题/问题。

SaveResult:

public static <T extends AddChg> void SaveResult(T r, Class c, String pk) { 
     EntityManager entityManager = Persistence.createEntityManagerFactory(
      "EntityLibraryPU").createEntityManager(); 
      entityManager.getTransaction().begin(); 
      r = entityManager.find(c, pk); 
      r.setSomething("01-banana"); 
      entityManager.persist(r); 
      entityManager.getTransaction().commit(); 
} 

RouteTopComponent:

public static void saveRecord() { 
    if (r.getRouteKey() != null) { 
     r.setRoute(txtRoute.getText()); 
    } 
    SaveResult.SaveResult(r, Route.class, r.getRouteKey()); 
} 

问题是与r.setSomething(""); 当我输入r。我唯一的建议是超类的建议(你必须参考这个问题的pastebin链接)。

在RouteTopComponent我能够做r.setRoute,而不是在SaveResult =(

Edit4:我一直奉行节约的TopComponent的实体特定数据的方法,同时使通用(普通)领域。超这里是我的代码看起来像现在:

RouteTopComponent:

public static void saveRecord() { 
     WWEntityManager.entityManager.getTransaction().begin(); 
     r = WWEntityManager.entityManager.find(Route.class, r.getRouteKey()); 
     r.setRoute(txtRoute.getText()); 
     WWEntityManager.entityManager.persist(r); 
     WWEntityManager.entityManager.getTransaction().commit(); 
     SaveResult.SaveResult(r, Route.class, r.getRouteKey()); 
    } 

正如你所看到的,我现在犯了Route.class具体领域第一。然后我调用SaveResult方法,然后保存通用的东西;

SaveResult

public class SaveResult { 

    public static <T extends AddChg> void SaveResult(T r, Class c, String pk) { 
     WWEntityManager.entityManager.getTransaction().begin(); 
     r = (T) WWEntityManager.entityManager.find(c, pk); 
     r.setChgDate("2012-05-31"); 
     WWEntityManager.entityManager.persist(r); 
     WWEntityManager.entityManager.getTransaction().commit(); 
    } 
} 

我想知道如果这确实是我应该处理的方式保存单个记录(2个提交)?它的工作原理,但如果有更好的方法来处理它,那将非常棒!

回答

2

我想去一个超类(我们称之为PersistentObject),从中所有实体都继承基本字段,例如Id。

然后,您的方法的参数将是一个PersistentObject而不是parcitular实体Route。您还可以定义该参数,因为如果你喜欢一个扩展持久性对象的任何类:

public <T extends PersistentObject> static void saveRecord(T newRecord) { 
    //your persistence logic here 
} 

This site解释了基础知识的好方法。

编辑:关于你的“EntityManager.find()”的问题:

您的选项似乎确定对我来说,作为EntityManager.find()方法返回主键检查如果第一参数实体确实是一个类,并检查第二个参数是否与实体主键的类型匹配。我认为你可以通过直接使用r.getClass()而不是使用Class c参数来节省一些麻烦。尽管如此,在SaveResult方法中做所有事情都需要你提供PK。

作为一个建议(如果它是单调乏味的或根本不可能的话就放弃它),你可以将find()逻辑提取到另一个方法,并将你获得的实体作为参数传递给save方法,具体属性。

还有另一种选择:NamedQueries。你可以在每个实体上定义一个“findById”查询,然后调用entity.createQuery方法返回你正在搜索的对象。这可以是“不!”在你的特殊情况下,因为你有100个实体,因此你必须做100个特定的查询(这里,复制粘贴是一个警报呼吁你造成灾难......)。

我从来没有这样做过,但也许你可以在映射的超类中创建一个独特的“findById”NamedQuery并传递相应的Id,但是你需要进行一些特定的处理。

编辑2:事实上,由于T类型扩展了AddChg,所以你知道你能够访问的唯一方法就是超类的方法。考虑到这一点(并避免矫枉过正),你可以在超类中定义一个“setRoute()”,并在你的特定类中重写它,给它你想要的特定行为。

如果你需要一个更复杂的方法,涉及许多特定于实例的属性,你需要在保存之前准备好你的对象。您的保存方法应只有存储对象所需的与持久性相关的操作。这个“setSomething()”似乎与对象数据本身有关,所以它更适合在RouteTopComponent中执行,就像你正在做的那样。

编辑3:只使用最后一个坚持。第一个坚持一半的信息,最后一个坚持一切。

+0

虽然这似乎是一个正确的解决方案,我不认为我可以使用它。除了对我有点困惑的事实,如果我在超类中声明了@id,它坚持我不能在子类中使用它。我必须在超类中拥有'@ id'。我无法真正解决这个问题,因为当前的应用程序结构依赖于所有具有'@ id'和其他元素的100个表。不知道如何解释,但如果有其他方法,除了超类化? –

+0

好点。我试着在超类中定义Id,并在子类中用'@AttributeOverride(name =“YOUR_ID_FIELD_NAME”,column = @Column(name =“YOUR_ID_COLUMN_NAME”))''覆盖它。该注释是在实体级别进行的,并未链接到字段。 – Gamb

+0

注释确实解决了错误。你能用我的代码进一步帮助我吗?你似乎很能理解这个概念。我修改了一些链接到我的实体类以及我的超类的实现我的问题。 –

1

使用泛型

让超

interface IParent 
{ 
    long getId(); 

    void setSomething(String smth); 
} 

每个实体implements IParent

public class SaveRecord 
{ 
    public static <T extends IParent> void saveRecord(T r) 
    { 
     EntityManager entityManager = Persistence.createEntityManagerFactory(
     "EntityLibraryPU").createEntityManager(); 
     entityManager.getTransaction().begin(); 
     r = entityManager.find(Route.class, r.getId()); 
     r.setSomething("01-banana"); 
     entityManager.persist(r); 
     entityManager.getTransaction().commit(); 
    }