2017-12-29 46 views
0

私は、多対多の単方向関係をhibernateと実装しようとしています。Hibernate分離エンティティが継承するために渡す

An exception occurred while running. null: InvocationTargetException: Failed to execute ApplicationRunner: detached entity passed to persist: dnd35cg.model.DnDClass; nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist: dnd35cg.model.DnDClass

これらは私のクラスである:

Hero.java

@Entity 
@Table(name = "HEROES") 
public class Hero { 

@Id 
@GeneratedValue(strategy = GenerationType.AUTO) 
@Column(name = "HERO_ID") 
private Long id; 

private Short strength; 
private Short dexterity; 
private Short constitution; 
private Short intelligence; 
private Short wisdom; 
private Short charisma; 
private String name; 

@ManyToOne 
private Race race; 

@ManyToMany(cascade = CascadeType.ALL) 
@JoinTable(name = "HERO_CLASSES", 
      joinColumns = { @JoinColumn(name = "HERO_ID") }, 
      inverseJoinColumns = { @JoinColumn(name = "DNDCLASS_ID") }) 
private Set<DnDClass> dnDClasses = new HashSet<>(); 

public Hero() { 
} 

public Hero(Short strength, Short dexterity, Short constitution, Short intelligence, Short wisdom, Short charisma, String name, Race race, Set<DnDClass> dnDClasses) { 
    this.strength = strength; 
    this.dexterity = dexterity; 
    this.constitution = constitution; 
    this.intelligence = intelligence; 
    this.wisdom = wisdom; 
    this.charisma = charisma; 
    this.name = name; 
    this.race = race; 
    this.dnDClasses = dnDClasses; 
} 

public Long getId() { 
    return id; 
} 

public Short getStrength() { 
    return strength; 
} 

public Short getDexterity() { 
    return dexterity; 
} 

public Short getConstitution() { 
    return constitution; 
} 

public Short getIntelligence() { 
    return intelligence; 
} 

public Short getWisdom() { 
    return wisdom; 
} 

public Short getCharisma() { 
    return charisma; 
} 

public String getName() { 
    return name; 
} 

public Race getRace() { 
    return race; 
} 

public Set<DnDClass> getDnDClasses() { 
    return dnDClasses; 
} 

@Override 
public String toString() { 
    return "Hero{" + 
      "id=" + id + 
      ", strength=" + strength + 
      ", dexterity=" + dexterity + 
      ", constitution=" + constitution + 
      ", intelligence=" + intelligence + 
      ", wisdom=" + wisdom + 
      ", charisma=" + charisma + 
      ", name='" + name + '\'' + 
      ", race=" + race + 
      ", dnDClasses=" + dnDClasses + 
      '}'; 
} 

public static HeroBuilder builder(){ 
    return new HeroBuilder(); 
} 

public static class HeroBuilder { 
    private Short strength; 
    private Short dexterity; 
    private Short constitution; 
    private Short intelligence; 
    private Short wisdom; 
    private Short charisma; 
    private String name; 
    private Race race; 
    private Set<DnDClass> dndClasses; 

    public HeroBuilder setStrength(Short strength) { 
     this.strength = strength; 
     return this; 
    } 

    public HeroBuilder setDexterity(Short dexterity) { 
     this.dexterity = dexterity; 
     return this; 
    } 

    public HeroBuilder setConstitution(Short constitution) { 
     this.constitution = constitution; 
     return this; 
    } 

    public HeroBuilder setIntelligence(Short intelligence) { 
     this.intelligence = intelligence; 
     return this; 
    } 

    public HeroBuilder setWisdom(Short wisdom) { 
     this.wisdom = wisdom; 
     return this; 
    } 

    public HeroBuilder setCharisma(Short charisma) { 
     this.charisma = charisma; 
     return this; 
    } 

    public HeroBuilder setName(String name) { 
     this.name = name; 
     return this; 
    } 

    public HeroBuilder setRace(Race race) { 
     this.race = race; 
     return this; 
    } 

    public HeroBuilder setDnDClasses(Set<DnDClass> dndClasses) { 
     this.dndClasses = dndClasses; 
     return this; 
    } 

    public Hero build() { 
     return new Hero(strength, dexterity, constitution, intelligence, wisdom, charisma, name, race, dndClasses); 
    } 
} 
} 

DnDClass私は、私は次のエラーを取得していますデータベースにいくつかの値を追加しようとすると問題があります.java

@Entity 
@Table(name = "DNDCLASSES") 
public class DnDClass { 

@Id 
@GeneratedValue(strategy = GenerationType.AUTO) 
@Column(name = "DNDCLASS_ID") 
private Long id; 

private String name; 
private Byte hitDie; 

public DnDClass() { 
} 

public DnDClass(String name, Byte hitDie) { 
    this.name = name; 
    this.hitDie = hitDie; 
} 

public Long getId() { 
    return id; 
} 

public void setId(Long id) { 
    this.id = id; 
} 

public String getName() { 
    return name; 
} 

public void setName(String name) { 
    this.name = name; 
} 

public Byte getHitDie() { 
    return hitDie; 
} 

public void setHitDie(Byte hitDie) { 
    this.hitDie = hitDie; 
} 

@Override 
public String toString() { 
    return "DnDClass{" + 
      "id=" + id + 
      ", name='" + name + '\'' + 
      ", hitDie=" + hitDie + 
      '}'; 
} 
} 

Dnd35cgApplication.java

@SpringBootApplication 
public class Dnd35cgApplication implements ApplicationRunner{ 

public static final Logger LOGGER = LoggerFactory.getLogger(Dnd35cgApplication.class); 
public static void main(String[] args) { 
    SpringApplication.run(Dnd35cgApplication.class, args); 
} 

@Autowired 
HeroRepository heroRepository; 

@Autowired 
RaceRepository raceRepository; 

@Autowired 
DnDClassRepository dnDClassRepository; 

@Override 
public void run(ApplicationArguments applicationArguments) throws Exception { 
    List<Race> races = new ArrayList<>(); 
    races.add(new Race("Human", "Medium", 30)); 
    races.add(new Race("Dwarf", "Medium", 20)); 
    races.add(new Race("Elf", "Medium", 30)); 
    races.add(new Race("Half-Elf", "Medium", 30)); 
    races.add(new Race("Half-Orc", "Medium", 30)); 
    races.add(new Race("Gnome", "Small", 20)); 
    races.add(new Race("Halfling", "Small", 20)); 

    for(Race r : races) 
     raceRepository.save(r); 

    List<DnDClass> classes = new ArrayList<>(); 
    classes.add(new DnDClass("Barbarian", (byte)12)); 
    classes.add(new DnDClass("Bard", (byte)6)); 
    classes.add(new DnDClass("Cleric", (byte)8)); 
    classes.add(new DnDClass("Druid", (byte)8)); 
    classes.add(new DnDClass("Fighter", (byte)10)); 
    classes.add(new DnDClass("Monk", (byte)8)); 
    classes.add(new DnDClass("Paladin", (byte)10)); 
    classes.add(new DnDClass("Ranger", (byte)10)); 
    classes.add(new DnDClass("Rogue", (byte)6)); 
    classes.add(new DnDClass("Sorcerer", (byte)4)); 
    classes.add(new DnDClass("Wizard", (byte)4)); 

    for(DnDClass c : classes) 
     dnDClassRepository.save(c); 

    List<Hero> initialHeroes = new ArrayList<>(); 

    Random rand = new Random(); 

    Set<DnDClass> dnDClassesSet = new HashSet<>(); 
    dnDClassesSet.add(dnDClassRepository.findById(1L)); 

    for (int i=0; i<=10; i++) { 
     initialHeroes.add(new Hero().builder().setName("Hero " + i) 
       .setStrength((short) (rand.nextInt(16) + 3)) 
       .setDexterity((short) (rand.nextInt(16) + 3)) 
       .setConstitution((short) (rand.nextInt(16) + 3)) 
       .setIntelligence((short) (rand.nextInt(16) + 3)) 
       .setWisdom((short) (rand.nextInt(16) + 3)) 
       .setCharisma((short) (rand.nextInt(16) + 3)) 
       .setRace(raceRepository.findById(rand.nextInt(7) + 1L)) 
       .setDnDClasses(dnDClassesSet) 
       .build()); 
    } 

    for (Hero h : initialHeroes) { 
     heroRepository.save(h); 
    } 

} 
} 

私はrunメソッドで新しいヒーローを構築していたとき、私は.setDnDClasses(dnDClassesSet)を使用していたときに問題があります。

ビルダーパターンを使用していて、適切なセッターを持っていない可能性があります。ヒーロークラスにはフィールドが多すぎるので、私は後でリファクタリングするつもりですが、現在はそのように実行していきたいと思います。

私は事前に何か助けていただきありがとうございます。

+0

問題は、 'dnDClassesSet.add(dnDClassRepository.findById(1L))'の行にある可能性があります。トランザクションがないので、 'DnDClass'は呼び出し直後にデタッチされます。実際にビジネスロジックをトランザクションサービスBeanメソッドに抽出する必要があります – crizzis

答えて

0

エラーを修正しました。

CascadeType.ALLが問題の原因です。理由はわかりませんが、削除したときに機能しました。

説明を歓迎します。

ありがとうございました。

関連する問題