【问题标题】:hibernate - Persisting a composition interface of strategy patternhibernate - 持久化策略模式的组合接口
【发布时间】:2018-12-10 19:26:02
【问题描述】:

我有以下类结构:

public abstract class Creature{
   private String name;
   //strategy pattern composition
   private SkillInterface skill;
}

public interface SkillInterface {
   void attack();
}

public class NoSkill implements SkillInterface {
   @Override
   public void attack() {
       //statements
   }
}

我的目标是将 Creature 对象保存在数据库的一个表中。 SkillInterface 的子类没有任何字段。当他们确定行为时,我想将选定的 SkillInterface 类名转换为字符串,因为我只需要保留当前生物技能策略的类名,使用像 Skill.getClass().getSimpleName() 这样的字符串。我尝试使用 @Converter 注释来实现它,使用 AttributeConverter 类将 SkillInterface 转换为 String 并保存,但总是有映射异常。我希望能够将其保存为 String 并检索为 SkillInterface 对象。

但是如何使用 Hibernate 实现它?还是我有设计错误?

【问题讨论】:

  • 你能把你的表结构和数据的样子贴出来吗?通过引用检索接口是什么意思?您打算检索整个对象吗?
  • 嗨,Amith,我编辑了我的问题并提供了更多详细信息。我想要做的是能够将 Creature 对象保存在数据库的一个表中。我想将SkillInterface转换为String,因为我只需要保留当前生物技能策略的类名。如果需要,可以提供更多详细信息。
  • 如果只需要持久化当前技能策略的名称,为什么不使用Enum来实现呢?
  • 只是想看看我是否可以使用接口实现和持久化策略模式,并且它只是子类。 Enum 可能是个好主意,但是添加所有方法声明并失去接口的灵活性不是一个整体的 Enum 吗?
  • 好的。因此,如果我正确理解您,您可能正在寻找与 DiscriminatorValue 相结合的继承。看看:stackoverflow.com/a/48415922/6505091

标签: java hibernate design-patterns database-design relational-database


【解决方案1】:

好吧,我好像找到了一个基本的解决方案,可以用来持久化策略模式接口实现。我使用 @Converter 注释和 AttributeConverter 类将策略类名称转换为列,同时保存到数据库并将检索到的字符串转换回策略类,如下所示:

@Entity
public class Creature {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;

    @Convert(converter = SkillConverter.class)
    private SkillInterface skill;
}

public class SkillConverter implements AttributeConverter<SkillInterface,String> {
    @Override
    public String convertToDatabaseColumn(SkillInterface skill) {
        return skill.getClass().getSimpleName().toLowerCase();
    }

    @Override
    public SkillInterface convertToEntityAttribute(String dbData) {
        //works as a factory
        if (dbData.equals("noskill")) {
            return new NoSkill();
        } else if (dbData.equals("axe")) {
            return new Axe();
        }
        return null;
    }
}

public interface SkillInterface {
    public String getSkill();

    void attack();
}


public class NoSkill implements SkillInterface{
    public String getSkill() {
        return getClass().getSimpleName();
    }

    @Override
    public void attack() {
        //strategy statements
    }
}

【讨论】:

  • 毫不奇怪,这也适用于 javax 持久性注解。
【解决方案2】:

您可以为您使用代理字段,如下所示:

abstract class Creature {
    @Column
    private String name;
    // strategy pattern composition
    private SkillInterface skill;

    @Column
    private String skillName;

    public String getSkillName() {
        return skill.getClass().getSimpleName();
    }

    public void setSkillName(String skillName) {
        //ignore
    }
}

【讨论】:

  • 我想过这种方式,但是每次检索对象时,您都需要一个额外的工厂模式来处理将 SkillName 字符串转换为 SkillInterface 子类。我认为在 Hibernate 中应该有一个更方便的解决方案,例如 @Convert 注释。它实际上是一个使用它的完美场所,但由于 MappingExceptions 或其他问题,我无法以某种方式构建它。
猜你喜欢
  • 1970-01-01
  • 2020-03-30
  • 2012-02-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-18
  • 2010-09-15
相关资源
最近更新 更多