Spring Data JPA @Query注解用法
原创
©著作权归作者所有:来自51CTO博客作者zhuhuix的原创作品,请联系作者获取转载授权,否则将追究法律责任
文章目录
@Query注解
可以通过手写JPQL语句,实现数据库查询
package org.springframework.data.jpa.repository;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.data.annotation.QueryAnnotation;
/**
* Annotation to declare finder queries directly on repository methods.
*
* @author Oliver Gierke
* @author Thomas Darimont
* @author Christoph Strobl
*
* @see Modifying
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
@QueryAnnotation
@Documented
public @interface Query {
/**
* Defines the JPA query to be executed when the annotated method is called.
*/
String value() default "";
/**
* Defines a special count query that shall be used for pagination queries to lookup the total number of elements for
* a page. If non is configured we will derive the count query from the original query or {@link #countProjection()} query if any.
*/
String countQuery() default "";
/**
* Defines the projection part of the count query that is generated for pagination. If neither {@link #countQuery()}
* not {@link #countProjection()} is configured we will derive the count query from the original query.
*
* @return
* @since 1.6
*/
String countProjection() default "";
/**
* Configures whether the given query is a native one. Defaults to {@literal false}.
*/
boolean nativeQuery() default false;
/**
* The named query to be used. If not defined, a {@link javax.persistence.NamedQuery} with name of
* {@code $ domainClass}.${queryMethodName}} will be used.
*/
String name() default "";
/**
* Returns the name of the {@link javax.persistence.NamedQuery} to be used to execute count queries when pagination is
* used. Will default to the named query name configured suffixed by {@code .count}.
*
* @see #name()
* @return
*/
String countName() default "";
}
用法
只需要将 @Query 标记在继承了 Repository 的自定义接口的方法上,就不需要遵循查询方法命名规则。支持命名参数及索引参数的使用
Using named queries to declare queries for entities is a valid approach and works fine for a small number of queries. As the queries themselves are tied to the Java method that executes them, you can actually bind them directly by using the Spring Data JPA @Query annotation rather than annotating them to the domain class. This frees the domain class from persistence specific information and co-locates the query to the repository interface.
示例:
public interface UserRepository extends JpaRepository<User, Long> {
@Query("select u from User u where u.emailAddress = ?1")
User findByEmailAddress(String emailAddress);
}
测试使用
1、定义一个实体类User
package com.zhuhuix.startup.security.domain;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.annotations.ApiModel;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;
import org.hibernate.sql.Update;
import javax.persistence.*;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.sql.Timestamp;
/**
* 用户表
*
* @author zhuhuix
* @date 2020-04-03
*/
@ApiModel(value = "用户信息")
@Entity
@Getter
@Setter
@Table(name = "user")
public class User implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@NotNull(groups = Update.class)
private Long id;
@Column(name = "user_name", unique = true)
private String userName;
@JsonIgnore
private String password;
/**
* 微信openId
*/
@Column(unique = true, name = "open_id")
private String openId;
/**
* 用户昵称
*/
@Column(name="nick_name")
private String nickName;
/**
* 性别 0-未知 1-male,2-female
*/
private Integer gender;
/**
* 头像地址
*/
@Column(name = "avatar_url")
private String avatarUrl;
@Column(name = "union_id")
private String unionId;
private String country;
private String province;
private String city;
private String language;
@Email
private String email;
private String phone;
private String remarks;
private Boolean enabled;
@JsonIgnore
@Column(name = "last_password_reset_time")
private Timestamp lastPasswordResetTime;
@JsonIgnore
@Column(name = "create_time")
@CreationTimestamp
private Timestamp createTime;
@JsonIgnore
@Column(name = "update_time")
@UpdateTimestamp
private Timestamp updateTime;
@Override
public String toString() {
return "User{" +
"id=" + id +
", userName='" + userName + '\'' +
", password='" + password + '\'' +
", openId='" + openId + '\'' +
", nickName='" + nickName + '\'' +
", gender=" + gender +
", avatarUrl='" + avatarUrl + '\'' +
", unionId='" + unionId + '\'' +
", country='" + country + '\'' +
", province='" + province + '\'' +
", city='" + city + '\'' +
", language='" + language + '\'' +
", email='" + email + '\'' +
", phone='" + phone + '\'' +
", remarks='" + remarks + '\'' +
", enabled=" + enabled +
", lastPasswordResetTime=" + lastPasswordResetTime +
", createTime=" + createTime +
", updateTime=" + updateTime +
'}';
}
}
2、定义UserRepository 接口
该接口继承JpaRepository默认的方法findById,通过@Query注解定义findByIdHql方法,通过@Query注解定义findByIdNateive方法
/**
* 用户DAO接口层
* @author zhuhuix
* @date 2020-04-03
*/
public interface UserRepository extends JpaRepository<User,Long>, JpaSpecificationExecutor<User> {
/**
* 该方法无需手工定义,JpaRepository父接口已存在
* 用于注册用户查找
* @param id id号
* @return 返回用户
*/
//User findById(String openId);
/**
* HQL 用于注册用户查找
* @param id id号
* @return 返回用户
*/
@Query("select u from User u where u.id=?1" )
User findByIdHql(Long id);
/**
* 原生SQL 用于注册用户查找
* @param id id号
* @return 返回用户
*/
@Query(value = "select * from user u where u.id=?1",nativeQuery =true)
User findByIdNative(Long id);
}
3、编写测试类测试
@SpringBootTest
@Slf4j
public class UserJPATest {
//测试方法findById
@Test
void test() {
UserRepository userRepository = SpringContextHolder.getBean(UserRepository.class);
User user = userRepository.findById(7L).get();
System.out.println(user.toString());
}
}
测试结果如下:(JPA自动生成SQL语句)
@SpringBootTest
@Slf4j
public class UserJPATest {
//测试方法findByIdHql
@Test
void test3(){
UserRepository userRepository = SpringContextHolder.getBean(UserRepository.class);
User user = userRepository.findByIdHql(7L);
System.out.println(user.toString());
}
}
测试结果如下:(JPA解析@Query注解中的HQL语句后生成SQL语句)
@SpringBootTest
@Slf4j
public class UserJPATest {
//测试方法findByIdNative
@Test
void test2(){
UserRepository userRepository = SpringContextHolder.getBean(UserRepository.class);
User user = userRepository.findByIdNative(7L);
System.out.println(user.toString());
}
}
测试结果如下:(JPA使用@Query注解中的原生SQL语句)
4、注意点
在@Query注解中使用原生SQL语句中,需显示声明 nativeQuery =true.