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 个屏幕中的每一个中都使用该方法,那么一切都会奏效;但是我正在考虑将其提取到自己的类中。这意味着它不会总是 Route,但可以是 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();
}

我遇到的问题之一 - 如果我将 'r' 传递给它,它期待 entity.Route。但如果我通过希普维亚,它就会坏掉。有什么方法可以让它期待像 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 Screen,则该行应为;

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:上面的解决方案有效,最后我有最后一个问题/问题。

保存结果:

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();
 }

路由顶部组件:

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 中的方法,同时将通用(公共)字段留给超类。这是我的代码现在的样子:

路由顶部组件:

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 方法,然后保存通用的东西;

保存结果

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 次提交)的方式?它有效,但如果有更好的做法来处理它,那将是非常棒的!

4

2 回答 2

2

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

然后,您的方法的参数将是 PersistentObject 而不是特定实体 Route。如果您愿意,您还可以将参数定义为任何扩展 PersistentObject 的类:

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

这个网站以一种很好的方式解释了基础知识。

编辑:关于您的“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:只需使用最后一个坚持。第一个保留一半信息,最后一个保留所有信息。

于 2012-05-29T14:16:22.797 回答
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();
   }
于 2012-05-29T14:37:44.410 回答