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

Nathalie picture Nathalie · Jun 10, 2013 · Viewed 8.8k times · Source

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

Answer

Carsten picture Carsten · Jun 11, 2013

@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);