如何在Play框架中从超类继承模型

6

我正在尝试理解在Play框架中继承是如何工作的!但目前还没有成功。

因此,我有这样一个超类:

@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)  
abstract class SuperClass extends Model {  
    @Id  
    @GeneratedValue(strategy = GenerationType.TABLE, generator = "SEQ_TABLE")   
    @TableGenerator(name = "SEQ_TABLE")  
    Long id;  

    int testVal;
}

还有两个继承类:

@Entity
public class Sub extends SuperClass {        
    String name;

    @Override
    public String toString() {
            return name;
    }
}

@Entity
public class Sub1 extends SuperClass {        
    String name;

    @Override
    public String toString() {
            return name;
    }
}

此外,我有两个用于继承类的控制器:
public class Subs and Sub1s extends CRUD {

}

应用程序启动后,我在MySQL数据库中收到了我的模型(Sub和Sub1)的两个表,其结构如下:id bigint(20),name varchar(255),没有超类中的testVal
当我尝试在CRUD界面中创建Sub类的新对象时,我收到了这样的错误:在模板{module:crud}/app/views/tags/crud/form.html中发生执行错误。引发的异常是MissingPropertyException:models.Sub没有名为testVal的属性。 在{module:crud}/app/views/tags/crud/form.html(大约第64行)中 #{crud.numberField name:field.name, value:(currentObject ? currentObject[field.name] : null) /} 问题:
  1. 我应该怎么做才能正确为继承模型生成MySQL表并修复错误?
  2. 是否可以为多个继承类拥有一个单一的superController?

1
请注意,您需要使用默认访问修饰符声明字段。将其更改为public,以便play PropertiesEnhaner可以正常工作。 - sdespolit
谢谢。我已经将Long idint testVal添加了公共访问权限。现在我可以在CRUD界面中看到testVal字段,并且可以保存模型而不出错。但是在MySql中仍然没有这样的字段,所以我无法保存此值。我相信我应该为此值添加某种注释,但是是什么呢? - gl0om
最终,我找到了解决方案:我只需将 @MappedSuperclass 添加到 SuperClass 中并从中删除 Long idsdespolit,如何接受您的建议添加公共访问修饰符?我找不到任何接受按钮。 - gl0om
1
你不能接受评论,但可以写下自己的答案总结所有内容。我不会反对。 - sdespolit
顺便提一下,确保您了解该策略的缺点http://docs.jboss.org/hibernate/stable/annotations/reference/en/html/entity.html#d0e1191。此外,我已经在postgresql中测试了您的模式(如您第一条评论中所述但不包括id),它可以正常工作。 - sdespolit
这是针对Play 1还是Play 2的?请编辑您的帖子以使其清晰明了。 - Moebius
2个回答

2

感谢 sdespolit,我做了一些实验。以下是我的实验结果:

超类:

@MappedSuperclass
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class SuperClass extends Model {
}

继承类:
@Entity 
public class Sub extends SuperClass {
}

我用以下方式制作了“超级控制器”:

"超级控制器"是我制作的一种工具:

@With({Secure.class, SuperController.class})
@CRUD.For(Sub.class)
public class Subs extends CRUD {
}

@With({Secure.class, SuperController.class})
@CRUD.For(Sub1.class)
public class Sub1s extends CRUD {
}

@CRUD.For(Sub.class) 用于指定该拦截器所使用的类

public class SuperController extends Controller {

    @After/Before/Whatever
    public static void doSomething() {
        String actionMethod = request.actionMethod;
        Class<? extends play.db.Model> model = getControllerAnnotation(CRUD.For.class).value();

        List<String> allowedActions = new ArrayList<String>();
        allowedActions.add("show");
        allowedActions.add("list");
        allowedActions.add("blank");

        if (allowedActions.contains(actionMethod)) {
            List<SuperClass> list = play.db.jpa.JPQL.instance.find(model.getSimpleName()).fetch();
        }
    }
}

我不确定doSomething()方法是否真正符合Java风格/Play!风格。但它对我有效。请告诉我是否有更本地化的方式来捕获模型类。


1

"表格每类是JPA规范的可选功能,因此并非所有提供程序都支持它"来自WikiBook

为什么不使用@MappedSuperclass?此外,您应该扩展GenericModel。在您的示例中,您定义了两次id,这也可能是问题的原因。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接