hibernate - Persisting a composition interface of strategy pattern

Multi tool use
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. Subclasses of SkillInterface are without any fields. 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(). I tried to implement it with @Converter annotation, using AttributeConverter class to convert SkillInterface to String and save, but always had mapping exceptions. I want to be able to save it as String and retrieve as SkillInterface object.
But how can I implement it with Hibernate? Or do I have a design mistake?
Hi Amith, I edited my question and gave more details. What I want to do is to be able to save Creature object at one table in database. I want to convert SkillInterface to String, as I only need to persist the classname of the current skill strategy of creature. Can provide more details if needed.
– gaiztoak
Jul 3 at 7:13
If you only need to persist the name of the current skill strategy, why not use Enum to achieve something like that?
– kaba713
Jul 3 at 8:42
Just wanted to see if I could implement and persist a Strategy Pattern using interfaces and it's subclasses only. Enum may be a good idea, but wouldn't it be a monolithic Enum to add all method declarations and to lose flexibility of an Interface?
– gaiztoak
Jul 3 at 8:48
OK. SO if I understand you correctly the thing you are probably looking for Inheritance combined with a DiscriminatorValue. Take a look at: stackoverflow.com/a/48415922/6505091
– kaba713
Jul 3 at 10:09
2 Answers
2
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
}
}
I thought about this way, but you will need an additional Factory Pattern to handle conversion of skillName string to an SkillInterface subclass everytime you retrieve an object. I think there should be a more convenient solution for this within Hibernate, such as @Convert annotation. It is actually a perfect place to use it but I couldn't achieve to build it somehow because of MappingExceptions or other problems.
– gaiztoak
Jul 3 at 8:20
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:
@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
}
}
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
Can you also post your table structure and how the data should look like ? And what do you mean by retrieve interface by reference? Are you planning to retrieve whole object ?
– Amith Kumar
Jul 3 at 2:13