@Query 取值方式
https://spring.io/blog/2014/07/15/spel-support-in-spring-data-jpa-query-definitions
@Query("select u from User u where u.age = ?#{[0]}")List<User> findUsersByAge(int age);# 实体取值@Query("select u from User u where u.firstname = :#{#customer.firstname}")List<User> findUsersByCustomersFirstname(@Param("customer") Customer customer);
@Query 使用方式
https://docs.spring.io/spring-data/jpa/docs/2.5.6/reference/html/#jpa.query-methods.at-query
public interface UserRepository extends JpaRepository<User, Long> {@Query("select u from User u where u.emailAddress = ?1")User findByEmailAddress(String emailAddress);@Query("select u from User u where u.emailAddress = :emailAddress")User findByEmailAddress2(@Param("nickname") String emailAddress);# 实体取值@Query("select u from User u where u.firstname = :#{#customer.firstname}")List<User> findUsersByCustomersFirstname(@Param("customer") Customer customer);}
Repository 的使用
https://docs.spring.io/spring-data/jpa/docs/2.5.6/reference/html/#jpa.query-methods.query-creation
| Keyword | Sample | JPQL snippet |
|---|---|---|
Distinct |
findDistinctByLastnameAndFirstname |
select distinct … where x.lastname = ?1 and x.firstname = ?2 |
And |
findByLastnameAndFirstname |
… where x.lastname = ?1 and x.firstname = ?2 |
Or |
findByLastnameOrFirstname |
… where x.lastname = ?1 or x.firstname = ?2 |
Is, Equals |
findByFirstname, findByFirstnameIs, findByFirstnameEquals |
… where x.firstname = ?1 |
Between |
findByStartDateBetween |
… where x.startDate between ?1 and ?2 |
LessThan |
findByAgeLessThan |
… where x.age < ?1 |
LessThanEqual |
findByAgeLessThanEqual |
… where x.age <= ?1 |
GreaterThan |
findByAgeGreaterThan |
… where x.age > ?1 |
GreaterThanEqual |
findByAgeGreaterThanEqual |
… where x.age >= ?1 |
After |
findByStartDateAfter |
… where x.startDate > ?1 |
Before |
findByStartDateBefore |
… where x.startDate < ?1 |
IsNull, Null |
findByAge(Is)Null |
… where x.age is null |
IsNotNull, NotNull |
findByAge(Is)NotNull |
… where x.age not null |
Like |
findByFirstnameLike |
… where x.firstname like ?1 |
NotLike |
findByFirstnameNotLike |
… where x.firstname not like ?1 |
StartingWith |
findByFirstnameStartingWith |
… where x.firstname like ?1(parameter bound with appended %) |
EndingWith |
findByFirstnameEndingWith |
… where x.firstname like ?1(parameter bound with prepended %) |
Containing |
findByFirstnameContaining |
… where x.firstname like ?1(parameter bound wrapped in %) |
OrderBy |
findByAgeOrderByLastnameDesc |
… where x.age = ?1 order by x.lastname desc |
Not |
findByLastnameNot |
… where x.lastname <> ?1 |
In |
findByAgeIn(Collection<Age> ages) |
… where x.age in ?1 |
NotIn |
findByAgeNotIn(Collection<Age> ages) |
… where x.age not in ?1 |
True |
findByActiveTrue() |
… where x.active = true |
False |
findByActiveFalse() |
… where x.active = false |
IgnoreCase |
findByFirstnameIgnoreCase |
… where UPPER(x.firstname) = UPPER(?1) |
返回自定义实体
推荐第一种:定义返回实体接口
定义返回实体接口
// 只需要有get方法即可,注意命名要规范public interface UserOrRole2 {String getId();String getUserId();String getNickname();String getSex();String getRoleName();}/*** jpql 返回自定义 实体* @param nickname* @return*/@Query(value = " SELECT u.userId,u.id,u.nickname,u.sex,u.roleName FROM UserBean u where u.nickname = :nickname ")public List<UserOrRole2> test(@Param("nickname") String nickname);
定义返回实体
public class UserOrRole2 {String id;String userId;String nickname;String sex;String roleName;// 省略get set}/*** jpql 返回自定义 实体* @param nickname* @return*/@Query(value = " SELECT new com.tn.jpahi.bean.UserOrRole2(r.userId,r.id,u.nickname,u.sex,r.roleName) FROM UserBean u where u.nickname =:nickname ")public List<UserOrRole2> test(@Param("nickname") String nickname);
常用注解
设置索引 @Table @Index @UniqueConstraint
unique = true 唯一索引
// 复合注解@Table(name = "数据表名称", schema = "数据库名称",indexes = {@Index(name = "索引名称", columnList = "字段1", unique = true),@Index(name = "索引名称", columnList = "字段1,字段2", unique = true),})@Table(name="数据表名称",indexes={@Index(name="索引名称",columnList="字段1",unique=true})// 单个注解@Index(name="索引名称",columnList="字段1",unique=false)})// 单个注解 - 唯一索引@UniqueConstraint(name = "索引名称", columnNames = {"字段1","字段2"})})
标识实体类中属性与数据表中字段的对应关系 @Column
columnDefinition我常用@Column(columnDefinition = " int(4) not null default 1 comment ' 停启用状态(0、停用 ,1、启用,默认1)' ")private Integer status;
根据属性设置
@Target({ElementType.METHOD, ElementType.FIELD})@Retention(RetentionPolicy.RUNTIME)public @interface Column {String name() default ""; // 定义了该属性字段在数据库表中所对应字段的名称boolean unique() default false; //表示该字段是否为唯一标识,默认为falseboolean nullable() default true; //表示该字段是否可以为null值,默认为trueboolean insertable() default true; //表示在使用“INSERT”脚本插入数据时,是否允许插入该字段的值boolean updatable() default true; //表示在使用“UPDATE”脚本插入数据时,是否允许更新该字段的值.String columnDefinition() default ""; //表示创建表时,该字段创建的SQL语句,一般用于通过Entity生成表定义时使用。String table() default ""; //定义了包含当前字段的表名,缺省值时默认该字段存在于主表下int length() default 255; // 表示字段的长度,当字段的类型为varchar时,该属性才有效,默认为255个字符int precision() default 0; //表示数值的总长度int scale() default 0; //表示小数点所占的位数}
实体中嵌入对象
https://www.codeleading.com/article/81262695760/ @Embeddable
@Access @embedded
默认使用方式
公共字段,需要被嵌入到其他地方使用
package com.detabes.gzyanalysis.entity.door;import lombok.Getter;import lombok.Setter;import org.hibernate.annotations.DynamicInsert;import org.hibernate.annotations.DynamicUpdate;import org.hibernate.annotations.SelectBeforeUpdate;import javax.persistence.Access;import javax.persistence.AccessType;import javax.persistence.Column;import javax.persistence.Embeddable;/*** 门禁实体公共字段** @author tn* @date 2022-03-03 11:02*/@Embeddable@DynamicInsert@DynamicUpdate@SelectBeforeUpdate@Access(AccessType.FIELD)@Getter@Setterpublic class DoorEntity {/*** 用户编码;用户编码**/@Column(columnDefinition = "varchar(60) comment '用户编码'")private String userNo;/*** 闸机号;闸机号**/@Column(columnDefinition = "varchar(60) not null comment '闸机号'")private String gateNo;}
实体类使用嵌入字段
package com.detabes.gzyanalysis.entity.door;import com.detabes.gzyanalysis.entity.CommonBean;import lombok.Data;import lombok.EqualsAndHashCode;import org.hibernate.annotations.DynamicInsert;import org.hibernate.annotations.DynamicUpdate;import javax.persistence.Column;import javax.persistence.Embedded;import javax.persistence.Entity;import javax.persistence.Table;/*** 入馆数据实体类** @author tn* @date 2022-03-03**/@Entity@Table(name = "door_input")@org.hibernate.annotations.Table(appliesTo = "door_input", comment = "入馆数据")@Data@EqualsAndHashCode(callSuper = true)@DynamicUpdate@DynamicInsertpublic class DoorInputEntity extends CommonBean<DoorInputEntity> {/*** 入馆时间;入馆时间**/@Column(columnDefinition = "varchar(60) comment '入馆时间'")private String inTime;/*** 入馆方式;0.不明 1. 扫码 2. 刷卡 3. 远程开门(保安开的 4. 等等**/@Column(columnDefinition = "int not null default 0 comment '入馆方式;0.不明 1. 扫码 2. 刷卡 3. 远程开门(保安开的 '")private Integer inType;/*** 嵌入公共字段对象*/@Embeddedprivate DoorEntity doorEntity;}
使用二 修改公共字段的column名称后在使用
公共字段
package com.detabes.gzyanalysis.entity.door;import lombok.Getter;import lombok.Setter;import org.hibernate.annotations.DynamicInsert;import org.hibernate.annotations.DynamicUpdate;import org.hibernate.annotations.SelectBeforeUpdate;import javax.persistence.Access;import javax.persistence.AccessType;import javax.persistence.Column;import javax.persistence.Embeddable;/*** 门禁实体公共字段** @author tn* @date 2022-03-03 11:02*/@Embeddable@DynamicInsert@DynamicUpdate@SelectBeforeUpdate@Access(AccessType.FIELD)@Getter@Setterpublic class DoorEntity {/*** 出入馆时间**/@Column(columnDefinition = "varchar(60) comment '出入馆时间'")private String times;/*** 出入馆方式;0.不明 1. 扫码 2. 刷卡 3. 远程开门(保安开的 4. 等等**/@Column(columnDefinition = "int not null default 0 comment '出入馆方式;0.不明 1. 扫码 2. 刷卡 3. 远程开门(保安开的 '")private Integer type;/*** 用户编码;用户编码**/@Column(columnDefinition = "varchar(60) comment '用户编码'")private String userNo;/*** 闸机号;闸机号**/@Column(columnDefinition = "varchar(60) not null comment '闸机号'")private String gateNo;}
实体类使用嵌入类时修改表字段名
这种方式如果要使用 索引方法如下:
// 嵌入类时修改表字段时, 不能写 DoorEntity 里面的原本实体字段名,会报错@Table(name = "door_input",indexes = {@Index(name = "in_type_index", columnList = "in_type", unique = true),})
import com.detabes.gzyanalysis.entity.CommonBean;import lombok.Data;import lombok.EqualsAndHashCode;import org.hibernate.annotations.DynamicInsert;import org.hibernate.annotations.DynamicUpdate;import javax.persistence.*;/*** 入馆数据实体类** @author tn* @date 2022-03-03**/@Entity@Table(name = "door_input")@org.hibernate.annotations.Table(appliesTo = "door_input", comment = "入馆数据")@Data@EqualsAndHashCode(callSuper = true)@DynamicUpdate@DynamicInsertpublic class DoorInputEntity extends CommonBean<DoorInputEntity> {/*** 嵌入公共字段对象*/@Embedded@AttributeOverrides({@AttributeOverride(name="type",column=@Column(name="in_type",columnDefinition = "int not null default 0 comment '入馆方式;0.不明 1. 扫码 2. 刷卡 3. 远程开门(保安开的 '")),@AttributeOverride(name="times",column=@Column(name="in_time",columnDefinition = "varchar(60) comment '入馆时间'"))})private DoorEntity doorEntity;}
效果
CREATE TABLE `door_input` (`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键,自动生成',`update_user_name` varchar(100) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '更新人',`create_user_name` varchar(100) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '创建人',`update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新日期',`create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建日期',`in_time` varchar(60) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '入馆时间',`in_type` int(11) NOT NULL DEFAULT '0' COMMENT '入馆方式;0.不明 1. 扫码 2. 刷卡 3. 远程开门(保安开的 ',`user_no` varchar(60) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '用户编码',`gate_no` varchar(60) COLLATE utf8mb4_general_ci NOT NULL COMMENT '闸机号',PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='入馆数据';
枚举参数
https://blog.csdn.net/weixin_42994251/article/details/110147426
枚举类
package com.detabes.gzyanalysis.enums;import lombok.AllArgsConstructor;import lombok.Getter;import java.util.Objects;/*** 存量类型** @author tn* @date 2022-01-19 16:31*/@AllArgsConstructor@Getterpublic enum StockTypeEnum {/* 总藏 = 在馆的所有书籍(包括外借的) */TOTAL(1,"总藏(在馆的所有书籍(包括外借的))"),/* 入藏 = 买的所有书籍*/INTO(2,"入藏(买的所有书籍)"),/* 在馆 = 在馆的所有书籍(不包括外借的) */AT_HOME(3,"在馆(在馆的所有书籍(不包括外借的))"),/* 总资源 =书+刊+古籍+多媒体+电子资源(这次不包括) */TOTAL_RESOURCE(4,"总资源(书+刊+古籍+多媒体+电子资源)"),;private final int stockType;private final String stockName;//获取枚举实例public static StockTypeEnum fromValue(Integer value) {for (StockTypeEnum stockTypeEnum : StockTypeEnum.values()) {if (Objects.equals(value, stockTypeEnum.getStockType())) {return stockTypeEnum;}}throw new IllegalArgumentException();}}
自定义Convert
package com.detabes.gzyanalysis.enums.convert;import com.detabes.gzyanalysis.enums.StockTypeEnum;import javax.persistence.AttributeConverter;/*** @author tn*/public class StockEnumConvert implements AttributeConverter<StockTypeEnum, Integer> {@Overridepublic Integer convertToDatabaseColumn(StockTypeEnum attribute) {return attribute.getStockType();}@Overridepublic StockTypeEnum convertToEntityAttribute(Integer dbData) {return StockTypeEnum.fromValue(dbData);}}
实体类中使用
import com.detabes.entity.basics.vo.SerializableVO;import com.detabes.gzyanalysis.enums.StockTypeEnum;import com.detabes.gzyanalysis.enums.convert.StockEnumConvert;import lombok.Data;import lombok.EqualsAndHashCode;import org.hibernate.annotations.DynamicInsert;import org.hibernate.annotations.DynamicUpdate;import javax.persistence.*;/*** 藏书存量(全馆全时间段统计)实体类** @author tn* @date 2022-01-19**/@Entity@Table(name = "library_stock", indexes = {@Index(name = "stockType_index", columnList = "stockType", unique = true)})@org.hibernate.annotations.Table(appliesTo = "library_stock", comment = "藏书存量(全馆全时间段统计)")@Data@EqualsAndHashCode(callSuper = true)@DynamicUpdate@DynamicInsertpublic class LibraryStockEntity extends SerializableVO<LibraryStockEntity> {/*** 主键;自增长**/@Id@GeneratedValue(strategy = GenerationType.IDENTITY)@Column(columnDefinition = "int comment '主键;自增长'")private Integer id;/*** 存量类型* 存储的是 int**/@Column(columnDefinition = "int comment '存量类型(具体信息:StockTypeEnum)'")@Convert(converter = StockEnumConvert.class)private StockTypeEnum stockType;/*** 统计时间**/@Column(columnDefinition = "varchar(100) not null comment '统计时间'")private String countTime;/*** 存量**/@Column(columnDefinition = "bigint default 0 comment '存量'")private Long stock;}
实体构建索引
// unique true: 唯一索引 false:单值索引@Table(name="sys_user_msg_collect",indexes={@Index(name="uuid_index",columnList="uuid",unique=true),@Index(name="loginName_index",columnList="loginName",unique=false)})
