Java JPA使用注意事项

JAVA JPA使用注意事项

共同需要遵守的

在进行数据删改时

使用@Modifying注解(标注只需要绑定参数的自定义的更新类语句(更新、插入、删除)),

@Transactional 事务

默认情况下,repository 接口中的CRUD方法都是被@Transactional注解修饰了的,对于读的操作方法,@Transactional注解的readOnly属性是被设置为true的,即只读;
CRUD中的其他方法被@Transactional修饰,即非只读。如果你需要修改repository 接口中的某些方法的事务属性,可以在该方法上重新加上@Transactional注解,并设置需要的属性。

in 语句写法

@Query(value = "select * from ee where identifynumber=?1 and yearmonth=?2 and syssource in (?3)  and (freetype='0' or freetype='' or  freetype is null) ", nativeQuery = true)
    public List findNoFreeByIdentifynumber( String identifynumber,String yearmonth, List syssource);

@Query 自定义SQL时

需要加上nativeQuery=true来声明这是一个本地查询哦。

取值方式::#{#obj.field} :value ?1

:#{#obj.field} 方式取值和:value方式取值不能一起用;

模糊查询

使用对象传参时

如果使用到模糊查询,需要将入参转成字符串(to_char)或者使用concat()函数转换,Oracle的只能拼接两个参数,但可以多次套接,MySQL可以无限参数拼接,比如:
CONCAT(CONCAT('%', :#{#pojo.query}), '%'))

使用参数传参时

可以直接使用||拼接字符串查询:比如:
LIKE '%'||:query||'%'

可配置查询(参数为空之类):

使用if语句(目前还没成功,转换成SQL的时候,会把if带过去,而SQL是没有if语句的,不清楚原因)

if(?1='' OR ?1 is null, 1=1, ?1=xx)

使用判空+OR

(:query is null OR a.fymc LIKE '%'||:query||'%')
注意: 如果需要判断的参数是数字型的,最好请在查询之前处理好,jpa目前不支持数字型参数为空(null),这里提供一个笨办法:入参前判断,如果参数为空,给它赋予一个特定值,语句里面使用这个特定值判断:(:query = -1 OR a.fymc LIKE '%'||:query||'%')

    /**
     * 查询诊疗价格(使用对象传参)
     * @param pojo
     * @return
     */
    @Query(value = " SELECT d.fymc entryName, d.fydj unitPrice, d.FYDW unit\n" +
            "    FROM (SELECT ROW_NUMBER() OVER (ORDER BY a.fyxh) rowNumber, a.fymc, b.fydj, a.fydw\n" +
            "    FROM gy_ylml a, gy_ylmx b\n" +
            "    WHERE a.fyxh = b.fyxh AND a.zfpb = 0 AND b.zfpb = 0 AND b.jgid = :#{#pojo.organizationId} " +
//            "        AND (:#{#pojo.query} is null OR a.fymc LIKE CONCAT(CONCAT('%', :#{#pojo.query}), '%')) )  d\n" +
            "        AND (:#{#pojo.query} is null OR a.fymc LIKE '%'||to_char(:#{#pojo.query})||'%') )  d\n" +
            " WHERE d.rowNumber BETWEEN ((:#{#pojo.pageNo} - 1) * :#{#pojo.pageSize} + 1) AND :#{#pojo.pageNo} * :#{#pojo.pageSize}", nativeQuery = true)
    List> getListFy(@Param("pojo") PricePojo pojo);
    
    /**
     * 查询诊疗价格(使用参数传参)
     * @param jgid
     * @param query
     * @param pageSize
     * @param pageNo
     * @return
     */
    @Query(value = " SELECT d.fymc entryName, d.fydj unitPrice, d.FYDW unit\n" +
            "    FROM (SELECT ROW_NUMBER() OVER (ORDER BY a.fyxh) rowNumber, a.fymc, b.fydj, a.fydw\n" +
            "    FROM gy_ylml a, gy_ylmx b\n" +
            "    WHERE a.fyxh = b.fyxh AND a.zfpb = 0 AND b.zfpb = 0 AND b.jgid = :jgid " +
            "     AND (:query is null OR a.fymc LIKE '%'||:query||'%'))  d\n" +
            " WHERE d.rowNumber BETWEEN ((:pageNo - 1) * :pageSize + 1) AND :pageNo * :pageSize", nativeQuery = true)
    List> getListFy (@Param("jgid") String jgid, @Param("query") String query, @Param("pageNo") Integer pageNo, @Param("pageSize") Integer pageSize);

@Query 自定义JPQL时

想要使用jpql的前提是你已经使用注解配置好了实体类以及参数

/**
 * @Entity 作用:指定当前类是实体类。
 * @Table 作用:指定实体类和表之间的对应关系。
 *  属性:
 *   name:指定数据库表的名称
 * @Id 作用:指定当前字段是主键。
 * @GeneratedValue  作用:指定主键的生成方式。。
 *  属性:
 *   strategy :指定主键生成策略。
 *   GenerationType.IDENTITY:自增,底层数据库必须支持自增(mysql)
 *   GenerationType.SEQUENCE:序列,底层数据库必须支持序列(oracle)
 *   GenerationType.TABLE:jpa提供的一种策略,通过生成一张表的方式完成主键自增,这张表存储了下一次添加的主键的值
 *   GenerationType.AUTO:由程序自动选择一种策略
 *
 * @Column
 *  作用:指定实体类属性和数据库表之间的对应关系
 *  属性:
 *   name:指定数据库表的列名称。
 *   unique:是否唯一
 *   nullable:是否可以为空
 *   inserttable:是否可以插入
 *   updateable:是否可以更新
 *   columnDefinition: 定义建表时创建此列的DDL
 *   secondaryTable: 从表名。如果此列不建在主表上(默认建在主表),该属性定义该列所在从表的名字搭建开发环境[重点]
 */
//示例:
@Entity //标注这是一个实体类
@Table(name = "tbl_user") //建立实体类与表的映射关系
public class User {
  @Id //声明此属性为主键
  @GeneratedValue(strategy = GenerationType.IDENTITY) //主键生成策略,自增
  @Column(name = "user_id")//指定属性对应数据库表的列名
  private Integer userId;

  @Column(name = "user_name")
  private String userName;

  @Column(name = "user_address")
  private String userAddress;

  @Column(name = "user_salary")
  private Double userSalary;
  
  //...getter setter toString方法
}

指定类接收查询结果时,如果参数和返回结果不对应

需要在实体类写一个初始化方法,查询语句中最好写上全路径,不然jpa可能找不到

    /**
     * 获取处方预付费列表
     *
     * @param brid
     * @param cfsbArr
     * @return
     */
    @Query(value = "SELECT new com.bsoft.gzjkpt.model.domain.GetPrecalculatedFeeCheckData(A.cfsb, A.fphm, A.mzxh, A.tybz, A.zfpb) " +
            "    FROM Ms_cf01 A " +
            "    WHERE A.jgid = ?1 AND 1 = 0 OR A.cfsb IN ?2 ")
    List getPrecalculatedFeeCheckData(@Param("jgid") String jgid, @Param("cfsb") List cfsbList, @Param("yjxh") List yjxhList);

你可能感兴趣的:(Java JPA使用注意事项)