如何在spring和hibernate中以一对多关系更新资源时去掉null值

时间:2017-03-07 08:33:04

标签: json spring hibernate rest api

我有两个类别和Ads.Category与广告有一对多的关系,即一个类别可以有多个广告。 我使用spring框架和hibernate作为ORM工具。 我的类别是:

@Entity
public class Category {
@Id
@GeneratedValue
private int cid;
private String cname;
@OneToMany(cascade = CascadeType.ALL)
@LazyCollection(LazyCollectionOption.FALSE)
@JoinColumn(name = "cid")
List<Ad> ads;
//getter and setter,constructor
}

我的广告类是:

@Entity
public class Ad {
@Id
@GeneratedValue
private int ad_id;
private String adName;
//getter and setter,constructor
}

我的类别控制器类是:

@Controller
public class CategoryController {
@Autowired
SessionFactory sessionFactory;
Session session;

@Transactional
@RequestMapping(value = "category",method = RequestMethod.POST)
@ResponseBody
public String insertCategory(@RequestBody Category category) throws SQLException{
    session=sessionFactory.getCurrentSession();
    session.save(category);
    return "succesful";
}

@Transactional
@RequestMapping(value = "updatecategory/{cid}",method = RequestMethod.PUT)
@ResponseBody
public String updateCategory(@RequestBody Category category,@PathVariable("cid") int cid) throws SQLException{
    Category category1=new Category();
    session=sessionFactory.getCurrentSession();
    category1= (Category) session.get(Category.class,cid);
    category1.setAds(category.getAds());
    session.save(category1);
    return "succesful";
}
}

我正在添加一个新的类别 本地主机:8080 /类别

{"cname":"automobile"}

我在此类别中插入广告,例如 本地主机:8080 / updatecategory / 1

{"ads":[{"adName":"car"}]}

它工作正常,但当我在同一类别中添加其他广告时,之前广告的外键cid更改为null

本地主机:8080 / updatecategory / 1

{"ads":[{"adName":"bike"}]}

类别表看起来像

cat_id  cName
1       automobile

广告表如下:

ad_id  adName  c_id
1       car    <null>
2       bike    1

4 个答案:

答案 0 :(得分:0)

您的代码存在多个问题。

您将Session对象存储为控制器的属性,尽管Session对象不是线程安全的。将其存储为方法中的变量。

updateCategory方法中,您无需创建新的Category对象并立即覆盖变量。

这里的主要问题是您没有为Ad对象设置后向引用。您应该使用适当的实体明确调用Ad#setCategory

答案 1 :(得分:0)

在设置ID的代码中:

@Id
@GeneratedValue
private int cid;

也许您需要为您的cid设置策略。

示例:

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int cid;

答案 2 :(得分:0)

您的代码会移除现有广告,并将其替换为新的广告列表。因此,Hibernate将旧广告的外键值设置为数据库中的null

为避免您需要将新广告添加到现有的广告列表中,请执行以下操作:

category1 = (Category) session.get(Category.class, cid);
category1.getAds().addAll(category.getAds());
session.save(category1);

而且,正如galovics所说,session不是thread-safe,所以在控制器类中将它作为方法局部变量而不是实例变量。

答案 3 :(得分:0)

花了一些时间后,我发现了问题所在。 用这个替换你的代码。它对我有用。

@Transactional
@RequestMapping(value = "updatecategory/{cid}", method = RequestMethod.PUT)
@ResponseBody
public String updateCategory(@RequestBody Category category, @PathVariable("cid") int cid) throws SQLException {
    Category category1;
    Session session = sessionFactory.getCurrentSession();
    category1 = (Category) session.get(Category.class, cid);
    category1.getAds().addAll(category.getAds());
    if (category1 != null) {
        session.save(category1);
        return "successful";
    } else
        return "unsuccessful";
}