简体   繁体   中英

HIBERNATE - ManyToOne - Not-null property references a null or transient value

I have a problem with Hibernate ManyToOne as the foreign key is not filled in the database.

So I have a Prepration Class and an Ingredients Class. The ingredientsId is supposed to be the foreign key in my Preparation Class.

In my Prepartion Class I have my ManyToOne Annotation. When I do not set nullable=false, I am able to fill the Preparation Table in my Database, but the foreign key stays "NULL". Wenn I set nullable=false I get - of course - an Error Message saying "Not-null property references a null or transient value..."

Maybe it is also something wrong with my PreparationDao...

I really do not know what I am doing wrong. I hope you can help me.

Thanks in advance and sorry in advance as this is my first question (after reading the guideline on how to ask I almost got affraid to ask :D ) and my problem might be also very stupid, but I'm an absolute beginner!

My Ingredients Class:

@Entity
@Table(name="tbl_ingredients")

public class Ingredients {
    @Id
    @GeneratedValue
    @Column(name="ingredients_id")
    private Integer id;
    private String name;
    private float percent;

//  @OneToMany(mappedBy="ingredients", cascade=CascadeType.ALL)
//  private Set<Preparation> preparation = new HashSet<Preparation>();
//
//
//  public Set<Preparation> getPreparation() {
//      return preparation;
//  }
//
//  public void setPreparation(Set<Preparation> preparation) {
//      this.preparation = preparation;
//  }

    //Konstrukturmethode der Klasse


    public Ingredients(){

    }

    public Ingredients(Integer id, String name, float percent){
        this(name,percent);
        setId(id);
    }

    public Ingredients(String name, float percent){
        setName(name);
        setPercent(percent);
    }

    public Integer getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public float getPercent() {
        return percent;
    }

    public void setPercent(float percent) {
        this.percent = percent;
    }
}

My Preparation Class:

@Entity
@Table(name="tbl_preparation")

public class Preparation {
    @Id
    @GeneratedValue
    @Column(name="preparation_id")
    private Integer id;
    private int amount;
    private String bevvalue;

    @ManyToOne (optional = false, fetch = FetchType.LAZY)
    @JoinColumn(name="ingredients_id", nullable=false)
    private Ingredients ingredients;

    @OneToMany(mappedBy="preparation")
    private Set<Cocktail> cocktail = new HashSet<Cocktail>();

    // Getter und Setter Methoden


    public Preparation(){

    }

    public Integer getId() {
        return id;
    }

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

    public int getAmount() {
        return amount;
    }

    public void setAmount(int amount) {
        this.amount = amount;
    }

    public Ingredients getIngredients() {
        return ingredients;
    }

    public void setIngredients(Ingredients ingredients) {
        this.ingredients = ingredients;
    }

    public String getBevvalue() {
        return bevvalue;
    }

    public void setBevvalue(String bevvalue) {
        this.bevvalue = bevvalue;
    }

    public Set<Cocktail> getCocktail() {
        return cocktail;
    }

    public void setCocktail(Set<Cocktail> cocktail) {
        this.cocktail = cocktail;
    }
}

PreparationDao:

public class PreparationDao extends HibernateDaoSupport {

    // Methode zum Anlegen der Zubereitung in der Datenbank



            // Methode zum Speichern der Zubereitung
            public Preparation save(Preparation preparation) {
                HibernateTemplate template = getHibernateTemplate();
                template.saveOrUpdate(preparation);
                return preparation;
            }
            // ing cocktailid muss wieder eingetragen werden        
            public void create(Integer [] ingredientsid, int amount, String bevvalue){ 
//              Set<Cocktail> cocktail = new HashSet<Cocktail>();
                HibernateTemplate template = getHibernateTemplate();
                Ingredients ingredients = (Ingredients) template.get(Ingredients.class, ingredientsid);
                Preparation p = new Preparation();
//              p.setCocktail(cocktail);
                p.setIngredients(ingredients);
                p.setAmount(amount);
                p.setBevvalue(bevvalue);
                template.saveOrUpdate(p);
            }

@rhinds is probably right about where the error is located.

The documentation to the hibernate template (which is from a very old spring version and imho shouldn't be used if not required by something out of your control) shows that the HibernateTemplate#get() only does not accept arrays of identifiers but is designed to work for a single identifier/return-object.

So to get a list of ingredients you would have to iterate over the list and fetch the ingredients one by one:

HibernateTemplate template = getHibernateTemplate();
Ingredients[] ingredients;
int i = 0;
for (int currentid: ingredientsid){
    ingredients[i] = (Ingredients) template.get(Ingredients.class, currentid);
    i++
}
Preparation p = new Preparation();
//              p.setCocktail(cocktail);
p.setIngredients(ingredients);

I solved the issue by changing my relation to "ManyToMany" and adjusting my create method... That's how it looks and works now:

My Preparation Class:

import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;

import javax.persistence.Table;

@Entity
@Table(name="tbl_preparation")

public class Preparation {
    @Id
    @GeneratedValue
    @Column(name="preparation_id")
    private Integer id;
    private String prepdesc;

    @ManyToMany(targetEntity=de.hdu.pms.model.Ingredients.class,
            cascade={CascadeType.PERSIST},
            fetch = FetchType.LAZY)
    @JoinTable(
            name="ingredientstopreparation",
            joinColumns={@JoinColumn(name="fk_preparation")},
            inverseJoinColumns={@JoinColumn(name="fk_ingredients")})
    private Set<Ingredients> ingredients;

    @ManyToOne
    @JoinColumn(name="fk_cocktail", nullable=false)
    private Cocktail cocktail;

My Preparation Dao:

public void create(Integer[] ingredientsnr, Integer cocktailid, String prepdesc){ 
    HibernateTemplate template = getHibernateTemplate();
    Cocktail cocktail = (Cocktail) template.get(Cocktail.class, cocktailid);
    Set<Ingredients> ingredients = new HashSet<Ingredients>();
    for (int ingredientsid : ingredientsnr){
        ingredients.add((Ingredients) template.get(Ingredients.class, ingredientsid));
    }
    Preparation p = new Preparation();
    p.setCocktail(cocktail);
    p.setIngredients(ingredients);
    p.setPrepdesc(prepdesc);
    template.saveOrUpdate(p);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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