springboot jpa 使用标准的动态 sql

springboot jpa 使用标准的动态 sql

 

第一种写法。在 service 层使用 @PersistenceUnit 注解,注入一个 EntityManagerFactory
    @PersistenceUnit
    private EntityManagerFactory emFactory; 

    @RequestMapping(value = "/sqltest", method = RequestMethod.POST) 
    public List<Car> sqltest(@RequestBody String brand){

        EntityManager em = emFactory.createEntityManager();  // 获得 EntityManager

        String sql = "select * from car where brand = :brand";

        List<Car> re = (List<Car>) em.createNativeQuery(sql, Car.class)
                .setParameter("brand", brand).getResultList();

        // 操作完数据库,需要显式关闭 entityManager,否则 entityManager 会一直保持这个数据库连接

        em.close();

        return re;

    }

 

查询结果集为包含 Map 的 List 的写法:

String sql = "select * from car where brand = :brand";

EntityManager em = emFactory.createEntityManager();

Query query = em.createNativeQuery(sql);    // import javax.persistence.Query;

query.unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);

List<Map<String, Object>> re = query.setParameter("brand", brand).getResultList();

 

注意,这种写法如果不关闭entityManager,em.close(); ,项目运行时间长了就会报错。

因为 entityManager 会一直保持数据库连接,不断开。

随着项目不断运行,mysql 的连接数(Threads_connected)会一直上涨:

javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: Unable to acquire JDBC Connection

Caused by: org.apache.tomcat.jdbc.pool.PoolExhaustedException: [pool-9-thread-1] Timeout: Pool empty. Unable to fetch a connection in 30 seconds, none available[size:100; busy:100; idle:0; lastwait:30000].

Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Data source rejected establishment of connection,  message from server: "Too many connections"

---------------------------------------------------

第二种写法。在 service 层使用 @PersistenceContext 注解注入 EntityManager:

这种写法,不需要操作完数据库显式的用 em.close() 关闭 entityManager推荐使用这种写法。

    @PersistenceContext
    private EntityManager em;

    @RequestMapping(value = "/sqltest", method = RequestMethod.POST)
    public List<Car> sqltest(@RequestBody String brand){
        String sql = "select * from car where brand = :brand";

        List<Car> re = (List<Car>) em.createNativeQuery(sql, Car.class)
                .setParameter("brand", brand).getResultList();

        return re;
    }

---------------------------------------------------

第三种写法。在 dao 层使用 @Query 注解,不过这种方法只能获得 List<Object[]>

@Query( value = "SELECT p.shop_id, sum(p.price) FROM product p GROUP BY p.shop_id", nativeQuery=true)
List<Object[]> getSumPriceGroupByShopId();

 

Spring Boot JPA(Java Persistence API)结合Spring框架提供了简化数据库访问和管理的强大工具。动态SQL,即在运行时构建和执行SQL查询,是JPA中一个高级功能,允许开发者在编写代码时动态构造SQL查询语句,而不是使用固定的预编译模板。 在Spring Boot中,使用动态SQL可以通过以下方式实现: 1. **Repository接口**:在Repository接口上,可以定义动态方法,这些方法的名称通常是`find*By*`形式,其中`*`会被查询条件替换。例如,`findByPropertyLike(String property, String pattern)`,这会生成动态SQL查询,如`SELECT * FROM table WHERE column LIKE :pattern`。 2. **JPA Criteria API**:JPA提供了Criteria API,允许在运行时构建复杂的查询条件。你需要创建一个`CriteriaBuilder`实例,然后使用其方法(如`eq`, `like`, `in`等)构建表达式,最后通过`CriteriaQuery`构建整个查询。 3. **Named Queries**:虽然不是直接的动态SQL,但你可以定义命名查询(@NamedQuery)并在代码中通过名称调用,查询内容是在配置文件中静态定义的。 4. **Querydsl**:这是一个强大的查询构建库,可以与Spring Data JPA集成,提供更灵活的动态SQL构建,支持复杂的逻辑表达式和类型安全的操作。 **相关问题--:** 1. 如何在Spring Boot JPA使用Criteria API? 2. Querydsl具体是如何简化动态SQL的? 3. Spring Data JPA中的命名查询是否支持动态参数?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值