我有两个类别和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
答案 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";
}