iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >JPA怎么使用nativequery多表关联查询返回自定义实体类
  • 838
分享到

JPA怎么使用nativequery多表关联查询返回自定义实体类

2023-06-25 16:06:03 838人浏览 安东尼
摘要

这篇文章主要介绍了JPA怎么使用nativequery多表关联查询返回自定义实体类,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。JPA nativequery多表关联查询返回

这篇文章主要介绍了JPA怎么使用nativequery多表关联查询返回自定义实体类,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。

JPA nativequery多表关联查询返回自定义实体类

JPA官方推荐的多表关联查询使用不便,接触的有些项目可能会使用JPA 做简单查询,Mybaits做复杂查询。所以想要寻找一种好用的解决方案。

JPA多表关联的实现方式

使用Specification实现映射关系匹配,如@ManyToOne等

使用NativeQuery等sql或hql来实现

优缺点对比

映射关系是hibernate的入门基础,很多人都会习惯去使用。个人不太喜欢这种方式,复用性太弱,且不灵活特别是在多表复杂业务情况下。

使用Specification方式需要继承JpaSpecificationExecutor接口,构造对应的方法后传入封装查询条件的Specification对象。逻辑上简单易懂,但是构造Specification对象需要拼接格式条件非常繁琐。

直接使用NativeQuery等方式实现复杂查询个人比较喜欢,直观且便利,弊端在于无法返回自定义实体类。需要手动封装工具类来实现Object到目标对象的反射

使用sql并返回自定义实体类

个人比较喜欢的实现方式,不多说看代码

import org.springframework.stereotype.Repository;import javax.persistence.EntityManager;import javax.persistence.PersistenceContext;import javax.transaction.Transactional; @Repositorypublic class EntityManagerDAO {    @PersistenceContext    private EntityManager entityManager;         @Transactional    public List<BackstageUserListDTO> listUser(){        String sql = "select a.create_time createTime," +                "a.mobilephone phoneNum," +                "a.email email,a.uid uid," +                "a.enabled enabled," +                "c.id_number idNumber," +                " (case b.`status` when 1 then 1 else 0 end) status " +                "from tbl_sys_user a " +                "LEFT JOIN user_high_qic b on a.uid=b.u_id" +                "LEFT JOIN user_qic c on a.uid=c.uid " +                "ORDER BY status desc";         SQLQuery sqlQuery = entityManager.createNativeQuery(sql).unwrap(SQLQuery.class);        Query query =      sqlQuery.setResultTransfORMer(Transformers.aliasToBean(BackstageUserListDTO.class));        List<BackstageUserListDTO> list = query.list();        entityManager.clear();        return list;    }}
public class BackstageUserListDTO implements Serializable{    private static final long serid = 1L;    private String createTime;    private String phoneNum;    private String email;    private BigInteger uid;    private Integer enabled;    private String idNumber;    private BigInteger status;    //GETTER SETTER}

这样一个需求如果使用前两种方式实现,无疑会非常麻烦。使用这种方式能够直接反射需要的自定义实体类。

可以根据需求整理封装成不同的方法,加入排序,分页等。我在这里主要提供一种方便的解决思路。

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

项目需求,查询需求数据需要多表链接——>根据多种条件筛选查询到的数据,在网上查了很多资料最终选择这个字符串拼接查询

类似如此动态查询

JPA怎么使用nativequery多表关联查询返回自定义实体类

以下是本人项目中使用总结

实体类

@Entity@Table(name = "signedorder")@Getter@Setter@NoArgsConstructor@EntityListeners(AuditingEntityListener.class)public class SignedOrder {    @Id    @GeneratedValue(strategy = GenerationType.IDENTITY)    @Column    private Integer id;//id    @CreatedDate    @Column(updatable = false)    private Date createTime;//创建时间    @LastModifiedDate    @Column    private Date lastModifiedTime;//修改时间    @ManyToOne(fetch = FetchType.EAGER, cascade = {            CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH    })    @JoinTable(name = "staff_signedorder", joinColumns = @JoinColumn(name =            "signedorder_id"), inverseJoinColumns = @JoinColumn(name = "staff_id"))    private Staff staff;//所属用户    @JoinColumn(name = "industry_id")    private Integer industryId;//行业Id}
@Entity@Table(name = "staff")@Getter@Setter@NoArgsConstructorpublic class Staff {     @Id    @GeneratedValue(strategy = GenerationType.IDENTITY)    @Column(name = "id")    private Integer id;//id    @Column(name = "name", length = 25)    private String name;//姓名    @JoinColumn(name = "city_id")    private Integer cityId;//城市id
@Entity@Table(name = "city")@Getter@Setter@NoArgsConstructor@Accessors(chain = true)public class City {    @Id    @GeneratedValue(strategy = GenerationType.IDENTITY)    @Column(name = "id")    private Integer id;//id    @Column(name = "name", length = 50)    private String name;//名称}//行业表和城市表一致,就不展示了

注解解释

实体类中相关注解解释:

  • @Entity: 对实体注释。任何Hibernate映射对象都要有这个注释

  • @Table: 声明此对象映射到数据库的数据表,该注释不是必须的,如果没有则系统使用默认值(实体的短类名)

  • @Getter @Setter@NoArgsConstructor:lombok提供注解,get、set方法及无参构造

  • @EntityListeners(AuditingEntityListener.class):加上此注解,时间注解@LastModifiedDate 和 @CreatedDate才可以生效

  • @Id: 声明此属性为主键

  • @GeneratedValue(strategy = GenerationType.IDENTITY):指定主键,

TABLE:使用一个特定的数据库表格来保存主键;

IDENTITY:主键由数据库自动生成(主要是自动增长型);

SEQUENCR:根据底层数据库的序列来生成主键,条件是数据库支持序列;

AUTO:主键由程序控制

  • @CreatedDate(updatable = false):创建时间时间字段,在insert的时候,会设置值;update时时间不变

  • @LastModifiedDate:修改时间段,update时会修改值

  • @ManyToOne(fetch = FetchType.EAGER, cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH}): 多对一,

FetchType.EAGER:立即加载, 获取关联实体;

CascadeType.MERGE: 级联更新;

CascadeType.PERSIST:级联新建;

CascadeType.REFRESH:级联刷新

  • @JoinTable: JoinColumn:保存关联关系的外键的字段;inverseJoinColumns:保存关系的另外一个外键字

  • @Column:用来标识实体类中属性与数据表中字段的对应关系

测试

@RunWith(SpringRunner.class)@SpringBootTestpublic class SprinBootMarketingsystemApplicationTests {    @PersistenceContext//jpa的数据库操作类    private EntityManager entityManger;    @Test    public void queryDb(){       //给参数赋值        Integer cityId = 1;        Integer industryId = 2;        Integer staffId = 16;        Date startTime = DateUtil.parse("1970-01-01");//字符串时间转换为date类型        Date endTime = Calendar.getInstance().getTime();//获取系统当前时间装换为date类型                //创建SQL语句主体        StringBuffer stringBuffer = new StringBuffer("\tSELECT\n" +                "\tcount( * ) count,\n" +                "\tci.NAME cityName\n" +                "\tFROM\n" +                "\tsignedorder s\n" +                "\tLEFT JOIN staff_signedorder t ON s.id = t.signedorder_id\n" +                "\tLEFT JOIN staff sta ON t.staff_id = sta.id\n" +                "\tLEFT JOIN city ci ON sta.city_id = ci.id\n" +                "\tWHERE\n" +                "\t1 = 1");         Map<String,Object> map =  new HashMap<>();         //拼接动态参数        if(industryId != null){                                      //industryId代表传进来的参数名称,给参数赋值nativeQuery.setParameter("industryId", industryId);             stringBuffer.append(" and s.industry_id = :industryId");             map.put("industryId",industryId);        }        if(cityId != null){            stringBuffer.append(" and ci.id = :cityId");            map.put("cityId",cityId);        }        if(staffId != null){            stringBuffer.append(" and sta.id = :staffId");            map.put("staffId",staffId);        }        if(startTime!=null && endTime!=null){            //使用这种赋值方式,时间类型需要给三个参数,参数名称,参数值,特定映射的类型TemporalType.DATE            //nativeQuery.setParameter("create_time", startTime,TemporalType.DATE);            stringBuffer.append( " and s.create_time BETWEEN :startTime and :endTime ");            map.put("startTime",startTime);            map.put("endTime",endTime);        }        Query nativeQuery = entityManger.createNativeQuery(stringBuffer.toString());        for (String key : map.keySet()) {            nativeQuery.setParameter(key, map.get(key));        }        //三种接受返回结果方式(第一种方式)               //第二种方式和第一种方式相似                //第三种方式:实体类接受        nativeQuery.unwrap(SQLQuery.class).setResultTransformer(Transformers.aliasToBean(TestVo.class));        List<TestVo> resultList = nativeQuery.getResultList();        for (TestVo svo:resultList        ) {            System.out.println(svo.toString());        }    }

打印结果

第一种方式打印结果

JPA怎么使用nativequery多表关联查询返回自定义实体类

第二种方式打印结果

JPA怎么使用nativequery多表关联查询返回自定义实体类

第三种方式打印结果

JPA怎么使用nativequery多表关联查询返回自定义实体类

TestVo实体接收类

@Datapublic class TestVo {    private String cityName;//城市名字    private BigInteger count;//签单数量(必须使用BigInteger类型接受)}

感谢你能够认真阅读完这篇文章,希望小编分享的“JPA怎么使用nativequery多表关联查询返回自定义实体类”这篇文章对大家有帮助,同时也希望大家多多支持编程网,关注编程网精选频道,更多相关知识等着你来学习!

--结束END--

本文标题: JPA怎么使用nativequery多表关联查询返回自定义实体类

本文链接: https://www.lsjlt.com/news/305855.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C++ 生态系统中流行库和框架的贡献指南
    作为 c++++ 开发人员,通过遵循以下步骤即可为流行库和框架做出贡献:选择一个项目并熟悉其代码库。在 issue 跟踪器中寻找适合初学者的问题。创建一个新分支,实现修复并添加测试。提交...
    99+
    2024-05-15
    框架 c++ 流行库 git
  • C++ 生态系统中流行库和框架的社区支持情况
    c++++生态系统中流行库和框架的社区支持情况:boost:活跃的社区提供广泛的文档、教程和讨论区,确保持续的维护和更新。qt:庞大的社区提供丰富的文档、示例和论坛,积极参与开发和维护。...
    99+
    2024-05-15
    生态系统 社区支持 c++ overflow 标准库
  • c++中if elseif使用规则
    c++ 中 if-else if 语句的使用规则为:语法:if (条件1) { // 执行代码块 1} else if (条件 2) { // 执行代码块 2}// ...else ...
    99+
    2024-05-15
    c++
  • c++中的继承怎么写
    继承是一种允许类从现有类派生并访问其成员的强大机制。在 c++ 中,继承类型包括:单继承:一个子类从一个基类继承。多继承:一个子类从多个基类继承。层次继承:多个子类从同一个基类继承。多层...
    99+
    2024-05-15
    c++
  • c++中如何使用类和对象掌握目标
    在 c++ 中创建类和对象:使用 class 关键字定义类,包含数据成员和方法。使用对象名称和类名称创建对象。访问权限包括:公有、受保护和私有。数据成员是类的变量,每个对象拥有自己的副本...
    99+
    2024-05-15
    c++
  • c++中优先级是什么意思
    c++ 中的优先级规则:优先级高的操作符先执行,相同优先级的从左到右执行,括号可改变执行顺序。操作符优先级表包含从最高到最低的优先级列表,其中赋值运算符具有最低优先级。通过了解优先级,可...
    99+
    2024-05-15
    c++
  • c++中a+是什么意思
    c++ 中的 a+ 运算符表示自增运算符,用于将变量递增 1 并将结果存储在同一变量中。语法为 a++,用法包括循环和计数器。它可与后置递增运算符 ++a 交换使用,后者在表达式求值后递...
    99+
    2024-05-15
    c++
  • c++中a.b什么意思
    c++kquote>“a.b”表示对象“a”的成员“b”,用于访问对象成员,可用“对象名.成员名”的语法。它还可以用于访问嵌套成员,如“对象名.嵌套成员名.成员名”的语法。 c++...
    99+
    2024-05-15
    c++
  • C++ 并发编程库的优缺点
    c++++ 提供了多种并发编程库,满足不同场景下的需求。线程库 (std::thread) 易于使用但开销大;异步库 (std::async) 可异步执行任务,但 api 复杂;协程库 ...
    99+
    2024-05-15
    c++ 并发编程
  • 如何在 Golang 中备份数据库?
    在 golang 中备份数据库对于保护数据至关重要。可以使用标准库中的 database/sql 包,或第三方包如 github.com/go-sql-driver/mysql。具体步骤...
    99+
    2024-05-15
    golang 数据库备份 mysql git 标准库
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作