如何在Thymeleaf中获取多对多关联中间表的数据?
解决多对多自动生成中间表的数据访问问题
JPA通过@JoinTable自动生成的中间表没有对应的实体类,所以无法直接用常规的findAll()方法访问。下面提供两种实用的解决方式:
方法一:手动创建中间表的实体类
这是最直接的方式,给自动生成的中间表创建对应的实体类,就能像操作普通表一样使用Repository方法。
步骤1:创建中间表实体类
假设你的中间表名为sale_product(对应@JoinTable(name = "sale_product")),表结构包含sale_id和product_id两个外键字段。创建实体类如下:
import jakarta.persistence.*; import java.io.Serializable; @Entity @Table(name = "sale_product") // 填写自动生成的中间表名称 public class SaleProduct implements Serializable { @EmbeddedId private SaleProductId id; // 可选:关联原实体,方便直接获取关联对象的属性 @ManyToOne @MapsId("saleId") @JoinColumn(name = "sale_id") private Sale sale; @ManyToOne @MapsId("productId") @JoinColumn(name = "product_id") private Product producto; // 构造函数、getter、setter省略 } // 复合主键类,必须实现Serializable @Embeddable class SaleProductId implements Serializable { @Column(name = "sale_id") private Long saleId; @Column(name = "product_id") private Long productId; // 构造函数、equals、hashCode、getter、setter省略 }
步骤2:创建Repository接口
import org.springframework.data.jpa.repository.JpaRepository; public interface SaleProductRepository extends JpaRepository<SaleProduct, SaleProductId> { }
步骤3:Controller中获取数据并传递到页面
@GetMapping("/verrelaciones") public String verRelacionesVentasProductos(Model model) { model.addAttribute("relaciones", this.saleProductRepository.findAll()); return "paginaRelaciones"; }
步骤4:Thymeleaf中展示数据
<tbody> <tr th:each="relacion:${relaciones}"> <td th:text="${relacion.id.saleId}"></td> <td th:text="${relacion.id.productId}"></td> <!-- 如果关联了原实体,可直接展示实体属性 --> <td th:text="${relacion.sale.numeroVenta}"></td> <td th:text="${relacion.producto.nombre}"></td> </tr> </tbody>
方法二:使用原生SQL/JPQL直接查询
如果不想创建实体类,可以通过原生SQL或JPQL直接查询中间表数据。
步骤1:在Repository中添加查询方法
比如在SaleRepository中添加:
import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.CrudRepository; import java.util.List; public interface SaleRepository extends CrudRepository<Sale, Long> { @Query(value = "SELECT sale_id, product_id FROM sale_product", nativeQuery = true) List<Object[]> findAllSaleProductRelations(); }
步骤2:Controller处理数据并传递
@GetMapping("/verrelaciones") public String verRelacionesVentasProductos(Model model) { List<Object[]> relaciones = this.saleRepository.findAllSaleProductRelations(); model.addAttribute("relaciones", relaciones); return "paginaRelaciones"; }
步骤3:Thymeleaf中展示
<tbody> <tr th:each="relacion:${relaciones}"> <td th:text="${relacion[0]}"></td> <!-- 对应sale_id --> <td th:text="${relacion[1]}"></td> <!-- 对应product_id --> </tr> </tbody>
注意事项
- 确认中间表的实际名称:可以直接查看数据库中
@JoinTable生成的表名,避免实体类映射错误。 - 使用复合主键时,主键类必须实现
Serializable,并重写equals()和hashCode()方法。
内容的提问来源于stack exchange,提问作者joaco1493
相关产品推荐
相关产品推荐

