Spring Data JPA @Query注解用法

@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.

原创文章 56 获赞 8 访问量 4740

猜你喜欢

转载自blog.csdn.net/jpgzhu/article/details/105511719