jpa多表关联动态查询(自定义sql语句)

项目中,jpa对于简单的数据库操作很方便,但如果多表关联动态查询时,需要自己去写SQL语句拼接查询条件,以下为本人学习的例子。
类似于这种多条件动态查询:
在这里插入图片描述
项目用的是springboot 2.1.0.RELEASE版本以及spring-boot-starter-data-jpa,其中spring-boot-starter-data-jpa底层已经依赖了hibernate-core5.3.7.Final,数据库用的是postgresql。
这里pom.xml和properties配置文件省略。
由于不能直接spring-data-jpa的Repository调用接口,所以得获取操作数据层的入口,详情请查看springBoot获取jpa的sessionFactory。
一.实体类(直接从工程复制粘贴过来的,有错可以自己解决,@Data为lombok工具的注解,自动生成getter/setter以及构造方法等)

**
 * 商品表
 */
@Entity
@Table(name = "t_goods ")//heibernate自动生成数据库表
@Data
public class TGoods implements Serializable {
	//这里关联两张表
	@Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @ApiParam("自增列")
    private int id;
    private String goodsId;//商品id
    private String goodsName;//商品名称
}
**
 * 商品规格表
 */
@Entity
@Table(name = "t_goods_spec ")
@Data
public class TGoodsSpec implements Serializable {
	//这里关联两张表
	@Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @ApiParam("自增列")
    private int id;
    private String goodsSpecId;//商品规格Id
    private String goodsName;//商品规格名称
    private String goodsId;//商品id
}
**
 * 库存表
 */
@Entity
@Table(name = "t_stock_statistics ")
@Data
public class TStockStatistics implements Serializable {
	//这里关联两张表
	@Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @ApiParam("自增列")
    private int id;
    private String goodsId;//商品id
    private String goodsSpecId;//商品规格Id
    private long totalAmount;//现有库存
}

二.测试JUnit代码

@RunWith(SpringRunner.class)
@SpringBootTest(classes = 对应的启动类.class)
public class ProviderApplicationTests {

    @PersistenceContext//jpa的数据库操作类
    private EntityManager entityManger;
    
    @Test
    public void test() throws Exception{
        String ids = "2,3";
        String supplier = "美的";
        String goodsName = "空调";
        String goodsSpecName = "1匹";
        String sql = "select t1.goods_id goodsId,t1.id id,t2.goods_name goodsName,t1.goods_spec_id goodsSpecId,t3.goods_spec_name goodsSpecName from t_stock_statistics t1 join t_goods t2 on t1.goods_id = t2.goods_id join t_goods_spec t3 on t3.spec_id = t1.goods_spec_id where 1=1";
        // 拼接动态查询条件的sql语句
        // 中的:supplier表示传进来的参数的名称
        // 另外一种传参方式是 其中1代表的是参数传进来的顺序号,比如 nativeQuery.setParameter(1, “美的”);
        Map map =  new HashMap<>();
        if(StringUtil.isNullOrEmpty(ids)){// 这里不把id作为查询条件
            sql += " and t1.id in (:ids)";
            map.put("ids",ids);
        }
        if(!StringUtil.isNullOrEmpty(supplier)){
            sql += " and t1.supplier = :supplier";
            map.put("supplier",supplier);
        }
        if(!StringUtil.isNullOrEmpty(goodsName)){
            sql += " and t2.goods_name = :goodsName";
            map.put("goodsName",goodsName);
        }
        if(!StringUtil.isNullOrEmpty(goodsSpecName)){
            sql += " and t3.goods_spec_name = :goodsSpecName";
            map.put("goodsSpecName",goodsSpecName);
        }
        sql += " order by id DESC";
        Query nativeQuery = entityManger.createNativeQuery(sql);
        // 把参数传进去
        for (String key:map.keySet()
             ) {
            if(key.equals("ids")){
                List idList = new ArrayList<>();
                String[] split = map.get(key).toString().split(",");
                for (String value:split
                     ) {
                    idList.add(Integer.valueOf(value));
                }
                nativeQuery.setParameter("ids", idList);
            } else {
                nativeQuery.setParameter(key, map.get(key));
            }
        }
        // 对查询出来的结果进行处理
        // 有三种处理方式,Transformers.ALIAS_TO_ENTITY_MAP为其中一种,另一个相似的是Transformers.TO_LIST
        nativeQuery.unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        List> resultList = nativeQuery.getResultList();
        for (Map map1 :resultList
             ) {
            System.out.println(map1);
        }
        // 这是第三种,Transformers.aliasToBean(StockStatisticsVO.class)意思为把查出来的结果转换成一个StockStatisticsVO实体类    
         /*nativeQuery.unwrap(SQLQuery.class).setResultTransformer(Transformers.aliasToBean(StockStatisticsVO.class));
          List resultList = nativeQuery.getResultList();
          for (StockStatisticsVO svo:resultList
             ) {
            System.out.println(svo.toString());
        }*/
    }
    }

附StockStatisticsVO实体类

/**
 * 仓库出入库VO
 */
@Data
public class StockStatisticsVO implements Serializable {
    //构造方法(无参)必须
    //VO类有的属性,sql查询语句必须有对应的返回字段值,顺序不分
    //postgresql返回字段名不分大小写,统一小写
    private int id;
    private String goodsid;//商品id
    private String goodsname;//商品名称
    private String goodsspecid;//商品规格Id
    private String goodsspecname;//商品规格名称

    public StockStatisticsVO() {
    }

}

测试结果:
jpa多表关联动态查询(自定义sql语句)_第1张图片

你可能感兴趣的:(springboot)