在一对多映射中向数据库添加行 (Hibernate/Spring)
Adding rows to a database in a one to many mapping (Hibernate/Spring)
编辑:仍然没有解决方案:/
我真的需要一些帮助来解决我已经坚持了 3 天的问题。我有一个包含两个 table 的数据库,设置如下:
DROP TABLE IF EXISTS `restaurant`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `restaurant` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`restaurant_name` TEXT,
`address` TEXT,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;
DROP TABLE IF EXISTS `restaurant_table`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `restaurant_table` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`table_size` int,
`table_number` int,
`restaurant_id` int(11),
PRIMARY KEY (`id`),
FOREIGN KEY (`restaurant_id`) references `restaurant`(`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;
这两个 table 之间存在一对多映射(因为在餐厅中可以有很多 Table)。我想在我的餐厅中添加一个 Table,但似乎做不到(或者有时我不能添加多个 table)。
如果有人能指出正确的方向或帮助我找出我的代码中究竟有什么问题,我将不胜感激。我已经尝试过不同的级联选项和更新而不是合并,但似乎从来没有让它工作过。我认为我的代码中可能存在根本性错误,也许我做这件事的整个方式都是错误的?
我的 Restaurant.java 文件:
@Entity
@Table(name="restaurant")
public class Restaurant {
@Id
@Column(name="id")
@GeneratedValue(strategy= GenerationType.IDENTITY)
private Long id;
@Column(name="restaurant_name")
private String restaurantName;
@Column(name="address")
private String address;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy="restaurant")
private List<RestaurantTable> table = new ArrayList<RestaurantTable>();
// Getters and setters
RestaurantTable.java:
@Entity
@Table(name="restaurant_table")
public class RestaurantTable {
@Id
@Column(name="id")
@GeneratedValue(strategy= GenerationType.IDENTITY)
private Long id;
@Column(name="table_size")
private int tableSize;
@Column(name="table_number")
private int tableNumber;
@ManyToOne
@JoinColumn(name="restaurant_id")
private Restaurant restaurant;
// Getters and setters
我的RestaurantTableController.java:
@Controller
public class RestaurantTableController {
@Autowired
private RestaurantService restaurantService;
@Autowired
private RestaurantTableService restaurantTableService;
@RequestMapping(value="restaurant/{id}/table", method = RequestMethod.GET)
public String addRestaurantTable(Model model, @PathVariable Long id) {
model.addAttribute("table", new RestaurantTable());
return "newTable";
}
@RequestMapping(value = "restaurant/{id}/table", method = RequestMethod.POST)
public String addRestaurantTable(@PathVariable Long id, @ModelAttribute ("table") RestaurantTable table) {
Restaurant restaurant = restaurantService.getRestaurant(id);
table.setRestaurant(restaurant);
restaurant.getTable().add(table);
restaurantService.mergeRestaurant(restaurant);
return "redirect:/bookings";
}
}
还有我在 RestaurantDaoImpl.java 中的 mergeRestaurant() 方法:
@Override
public void mergeRestaurant(Restaurant restaurant) {
Session session = this.sessionFactory.getCurrentSession();
session.merge(restaurant);
logger.info("Restaurant record updated successfully, Restaurant Details=" + restaurant);
}
我现在得到的错误是:
HTTP Status 500 - Request processing failed; nested exception is java.lang.IllegalStateException: Multiple representations of the same entity [RestaurantTable#6] are being merged. Detached: [Table number 6]; Detached: [Table number 5]
感谢任何帮助!
编辑:
已更改
private List<RestaurantTable> table = new ArrayList<RestaurantTable>();
到
private Set<RestaurantTable> table = new HashSet<RestaurantTable>();
此外,我将餐厅中的 "CascadeType.ALL" 移至 RestaurantTable.java。
现在,如果我尝试输入第一个 Table 进入餐厅,它会给我这个错误:
HTTP Status 500 - Request processing failed; nested exception is org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [RestaurantTable#6]
有什么想法吗?
首先,你的映射是正确的。请不要再尝试它了。一件事:我想有一个 @ManyToOne
部分作为懒惰的部分。但当然没有必要。
@Entity
@Table(name="restaurant")
public class Restaurant {
@Id
@Column(name="id")
@GeneratedValue(strategy= GenerationType.IDENTITY)
private Long id;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy="restaurant")
private List<RestaurantTable> table = new ArrayList<RestaurantTable>();
}
@Entity
@Table(name="restaurant_table")
public class RestaurantTable {
@Id
@Column(name="id")
@GeneratedValue(strategy= GenerationType.IDENTITY)
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name="restaurant_id")
private Restaurant restaurant;
}
看起来,您没有正确处理会话(或事务)。
您的 mergeRestaurant()
方法看起来是正确的(也许,我会将 merge()
更改为 saveOrUpdate()
)。所以问题出在其他方面。尝试使用另一种方法。
您通过外键关联 RestaurantTable
— 要添加 RestaurantTable
,您不需要更新 Restaurant
。您只需要 Restaurant
id
。试试更简单的方法
public void addTable(Long restaurantId, RestaurantTable table) {
Session session = this.sessionFactory.getCurrentSession();
Restaurant restaurant = (Restaurant)session.load(Restaurant.class, restaurantId);
table.setRestaurant(restaurant);
session.save(table);
}
session.load()
用于优化,它只是 returns 一个带有 restaurantId
的代理而不访问数据库。你甚至可以尝试使用
table.setRestaurant(new Restaurant(restaurantId));
意思是一样的。
编辑:仍然没有解决方案:/
我真的需要一些帮助来解决我已经坚持了 3 天的问题。我有一个包含两个 table 的数据库,设置如下:
DROP TABLE IF EXISTS `restaurant`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `restaurant` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`restaurant_name` TEXT,
`address` TEXT,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;
DROP TABLE IF EXISTS `restaurant_table`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `restaurant_table` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`table_size` int,
`table_number` int,
`restaurant_id` int(11),
PRIMARY KEY (`id`),
FOREIGN KEY (`restaurant_id`) references `restaurant`(`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;
这两个 table 之间存在一对多映射(因为在餐厅中可以有很多 Table)。我想在我的餐厅中添加一个 Table,但似乎做不到(或者有时我不能添加多个 table)。
如果有人能指出正确的方向或帮助我找出我的代码中究竟有什么问题,我将不胜感激。我已经尝试过不同的级联选项和更新而不是合并,但似乎从来没有让它工作过。我认为我的代码中可能存在根本性错误,也许我做这件事的整个方式都是错误的?
我的 Restaurant.java 文件:
@Entity
@Table(name="restaurant")
public class Restaurant {
@Id
@Column(name="id")
@GeneratedValue(strategy= GenerationType.IDENTITY)
private Long id;
@Column(name="restaurant_name")
private String restaurantName;
@Column(name="address")
private String address;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy="restaurant")
private List<RestaurantTable> table = new ArrayList<RestaurantTable>();
// Getters and setters
RestaurantTable.java:
@Entity
@Table(name="restaurant_table")
public class RestaurantTable {
@Id
@Column(name="id")
@GeneratedValue(strategy= GenerationType.IDENTITY)
private Long id;
@Column(name="table_size")
private int tableSize;
@Column(name="table_number")
private int tableNumber;
@ManyToOne
@JoinColumn(name="restaurant_id")
private Restaurant restaurant;
// Getters and setters
我的RestaurantTableController.java:
@Controller
public class RestaurantTableController {
@Autowired
private RestaurantService restaurantService;
@Autowired
private RestaurantTableService restaurantTableService;
@RequestMapping(value="restaurant/{id}/table", method = RequestMethod.GET)
public String addRestaurantTable(Model model, @PathVariable Long id) {
model.addAttribute("table", new RestaurantTable());
return "newTable";
}
@RequestMapping(value = "restaurant/{id}/table", method = RequestMethod.POST)
public String addRestaurantTable(@PathVariable Long id, @ModelAttribute ("table") RestaurantTable table) {
Restaurant restaurant = restaurantService.getRestaurant(id);
table.setRestaurant(restaurant);
restaurant.getTable().add(table);
restaurantService.mergeRestaurant(restaurant);
return "redirect:/bookings";
}
}
还有我在 RestaurantDaoImpl.java 中的 mergeRestaurant() 方法:
@Override
public void mergeRestaurant(Restaurant restaurant) {
Session session = this.sessionFactory.getCurrentSession();
session.merge(restaurant);
logger.info("Restaurant record updated successfully, Restaurant Details=" + restaurant);
}
我现在得到的错误是:
HTTP Status 500 - Request processing failed; nested exception is java.lang.IllegalStateException: Multiple representations of the same entity [RestaurantTable#6] are being merged. Detached: [Table number 6]; Detached: [Table number 5]
感谢任何帮助!
编辑: 已更改
private List<RestaurantTable> table = new ArrayList<RestaurantTable>();
到
private Set<RestaurantTable> table = new HashSet<RestaurantTable>();
此外,我将餐厅中的 "CascadeType.ALL" 移至 RestaurantTable.java。
现在,如果我尝试输入第一个 Table 进入餐厅,它会给我这个错误:
HTTP Status 500 - Request processing failed; nested exception is org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [RestaurantTable#6]
有什么想法吗?
首先,你的映射是正确的。请不要再尝试它了。一件事:我想有一个 @ManyToOne
部分作为懒惰的部分。但当然没有必要。
@Entity
@Table(name="restaurant")
public class Restaurant {
@Id
@Column(name="id")
@GeneratedValue(strategy= GenerationType.IDENTITY)
private Long id;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy="restaurant")
private List<RestaurantTable> table = new ArrayList<RestaurantTable>();
}
@Entity
@Table(name="restaurant_table")
public class RestaurantTable {
@Id
@Column(name="id")
@GeneratedValue(strategy= GenerationType.IDENTITY)
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name="restaurant_id")
private Restaurant restaurant;
}
看起来,您没有正确处理会话(或事务)。
您的 mergeRestaurant()
方法看起来是正确的(也许,我会将 merge()
更改为 saveOrUpdate()
)。所以问题出在其他方面。尝试使用另一种方法。
您通过外键关联 RestaurantTable
— 要添加 RestaurantTable
,您不需要更新 Restaurant
。您只需要 Restaurant
id
。试试更简单的方法
public void addTable(Long restaurantId, RestaurantTable table) {
Session session = this.sessionFactory.getCurrentSession();
Restaurant restaurant = (Restaurant)session.load(Restaurant.class, restaurantId);
table.setRestaurant(restaurant);
session.save(table);
}
session.load()
用于优化,它只是 returns 一个带有 restaurantId
的代理而不访问数据库。你甚至可以尝试使用
table.setRestaurant(new Restaurant(restaurantId));
意思是一样的。