简体   繁体   English

hibernate - 坚持策略模式的组合接口

[英]hibernate - Persisting a composition interface of strategy pattern

I have the following class structure: 我有以下类结构:

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
   }
}

My goal is to persist Creature objects at one table in database. 我的目标是将Creature对象持久保存在数据库中的一个表中。 Subclasses of SkillInterface are without any fields. SkillInterface的子类没有任何字段。 As they determine the behaviour, I want to convert selected SkillInterface class name to a String, as I only need to persist the classname of the current skill strategy of creature, with a String like skill.getClass().getSimpleName(). 当他们确定行为时,我想将选定的SkillInterface类名转换为String,因为我只需要保持生物当前技能策略的类名,使用像skill.getClass()。getSimpleName()这样的字符串。 I tried to implement it with @Converter annotation, using AttributeConverter class to convert SkillInterface to String and save, but always had mapping exceptions. 我尝试用@Converter注释实现它,使用AttributeConverter类将SkillInterface转换为String并保存,但始终有映射异常。 I want to be able to save it as String and retrieve as SkillInterface object. 我希望能够将其保存为String并检索为SkillInterface对象。

But how can I implement it with Hibernate? 但是如何用Hibernate实现呢? Or do I have a design mistake? 或者我有设计错误?

Ok looks like I have found a basic solution that can be used to persist Strategy Pattern interfaces implementations. 好吧,我发现我已经找到了一个可用于持久化策略模式接口实现的基本解决方案。 I used a @Converter annotation and a AttributeConverter class to convert strategy class names to column while saving to database and cast the retrieved String back to strategy class as following: 我使用@Converter注释和AttributeConverter类将策略类名转换为列,同时保存到数据库并将检索到的String转换回策略类,如下所示:

@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
    }
}

You can use a proxy field to this for you like below: 您可以在下面使用代理字段:

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
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM