DBIx和Perl中的继承

我目前正试图用DBIx实现以下场景:

表格产品包含“一般产品”和“捆绑产品”(捆绑产品是一般产品的集合):

package Product;
use base 'DBIx::Class::Core';
__PACKAGE__->table("products");
__PACKAGE__->add_columns(
  "productId",
  { data_type => "varchar", is_nullable => 0, size => 10},
  "name",
  { data_type => "varchar", is_nullable => 1, size => 150},
  "type",
  {
     data_type => "enum",
     default_value => "general",
     extra => {
       list => ["general", "bundle"],
     },
     is_nullable => 0,
  });

正如您所看到的,产品是一种通用产品,还是一种捆绑产品被保存在列类型中

现在我想将这些信息封装在类标识中:我想要有以下类:

  • 产品( type无关紧要)
  • BundleProduct( type ='bundle')
  • GeneralProduct( type ='general')
  • 我写了:

    package BundleProduct;
    use base 'Product';
    
    __PACKAGE__->resultset_attributes({ where => { 'type' => 'bundle' } });
    1;
    

    package GeneralProduct;
    use base 'Product';
    
    __PACKAGE__->resultset_attributes({ where => { 'type' => 'general' } });
    1;
    

    但是执行时

    my @allProducts = $schema->resultset('BundleProduct')->all;
    

    所有的一般产品都被提取。 尽管生成的对象是实例BundleProduct ,但生成的SQL包含类GeneralProduct的WHERE条件( type ='general')。 更糟糕的是:如果我试图获取ProductBundleProductGeneralProduct基类),则也应用条件type ='general'! 看来GeneralProduct中的定义会覆盖所有其他定义。

    我的设计有什么问题?


    不推荐使用resultset_attributes 。 您应该使用bundle_productsgeneral_products方法为Product实现结果集类:

    package My::Schema::ResultSet::Product;
    use base 'DBIx::Class::ResultSet';
    
    sub bundle_products  { shift->search({ type => 'bundle' }); }
    sub general_products { shift->search({ type => 'general' }); }
    

    然后你可以搜索这样的特定产品:

    $schema->resultset('Product')->bundle_products->all;
    $schema->resultset('Product')->general_products->all;
    

    请参阅resultset_attributes的文档。

    也看看DBIx :: Class :: DynamicSubclass。 子类化结果时,它增加了一些有用的功能。


    这可能稍微OT,但我似乎总是遇到一些阴险的应用程序实现问题,当处理我的模式中的枚举数据类型。

    所以我不再使用它们了。 我使用外键关系,并使用单个表或包含所有代码的组合表:

    <id, code_type, code_name> 
    < 1, 'product_type', 'bundle'>
    < 2, 'product_type', 'general'>
    

    然后我通过product.product_type_id = code_table.id从产品加入product_type

    这项技术使得应用程序的实现变得非常简单,但是在项目开始阶段以一些额外的数据库管理为代价。


    它可能总是默认为一般,因为数据没有被膨胀到一个Enum对象?

    感到惊讶的是,它没有给出明确的错误,但可能在下面添加(到Product包)将解决您的问题:

    __PACKAGE__->load_components(qw/InflateColumn::Object::Enum/);
    

    除上述之外,还可以尝试将is_enum => 1添加到您的类型列定义中:

    type => {
      data_type     => "enum",
      is_enum       => 1,  
      default_value => "general",
      is_nullable   => 0,
      extra => {
        list => ["general", "bundle"],
      },
    },
    

    NB。 这应该强制使用通胀对象( Object::Enum ),而如果没有它,我相信它会尝试使用您正在使用的RDBMS的本地枚举(如果存在的话)。

    手指穿过这件作品。 如果不尝试删除default_value ,看看这是如何影响的东西。

    链接地址: http://www.djcxy.com/p/64713.html

    上一篇: DBIx and inheritance in Perl

    下一篇: jQuery Ajax abort and new request in quick succession