You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 19:50:19