如果要实现实体类中属性的类型和数据库表中字段的类型相互转化,则需要使用 @Convert 注解

package javax.persistence;

import java.lang.annotation.Repeatable;
import java.lang.annotation.Target;
import java.lang.annotation.Retention;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME; @Repeatable(Converts.class)
@Target({METHOD, FIELD, TYPE})
@Retention(RUNTIME)
public @interface Convert { /**
* 指定要使用的转换器
*/
Class converter() default void.class; /**
* 当注解 Convert 应用在基本类型的属性或基本类型的元素集合上,不能指定attributeName元素。
*/
String attributeName() default ""; /**
* 用于禁用自动应用或继承的转换器。如果 disableConversion 为真,则不应指定converter元素
*/
boolean disableConversion() default false;
}

由 Convert 源码可知:使用 @Convert 注解需要一个转换器,

自定义转换器需要实现 AttributeConverter 接口

1、AttributeConverter 接口

package javax.persistence;

/**
*
* 把实体类中属性的类型与数据库表中字段的类型相互转换.
*
* @param <X> 实体类中的属性类型
* @param <Y> 数据库表中的字段类型
*/
public interface AttributeConverter<X,Y> { /**
* 实体类中属性的类型转换为数据库表中字段的类型
*
* @param 实体类中属性的类型
* @return 数据库表中字段的类型
*
*/
public Y convertToDatabaseColumn (X attribute); /**
* 数据库表中字段的类型转换为实体类中属性的类型
*
* @param 数据库表中字段的类型
* @return 实体类中属性的类型
*
*/
public X convertToEntityAttribute (Y dbData);
}

2、自定义的实现类

package com.chayiges;

import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
import java.time.YearMonth; /**
* 使用 JPA 将 YearMonth 持久化为整数
*
* @author chayiges
*/
// 标识该类是转换器
@Converter
public class YearMonthIntegerAttributeConverter
implements AttributeConverter<YearMonth, Integer> { /**
* 实体类 -> 数据库
* 向数据库中保存时调用
*/
@Override
public Integer convertToDatabaseColumn(YearMonth attribute) {
if (attribute != null) {
return (attribute.getYear() * 100) + attribute.getMonth().getValue();
}
return null;
} /**
* 数据库 -> 实体类
* 向数据库中查询时调用
*/
@Override
public YearMonth convertToEntityAttribute(Integer dbData) {
if (dbData != null) {
int year = dbData / 100;
int month = dbData % 100;
return YearMonth.of(year, month);
}
return null;
}
}

1.2、创建数据库对应的实体类

package com.chayiges;

import jp.co.isid.cas3.commons.api.jpa.AbstractAggregateRoot;
import jp.co.isid.cas3.onecas.core.YearMonthIntegerAttributeConverter;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor; import javax.persistence.Column;
import javax.persistence.Convert;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.Table;
import java.io.Serializable;
import java.time.YearMonth;
import java.util.UUID; /**
* 学生表对应的实体类
*
* @author chayiges
*/
@Entity
@Getter
@Table
@NoArgsConstructor(access = AccessLevel.PROTECTED, force = true)
@AllArgsConstructor
public class Student extends AbstractAggregateRoot<Student, UUID> implements Serializable { /** ID */
@EmbeddedId
private UUID id; /** 姓名 */
@Column(name = "user_name", length = 100, nullable = false)
private String userName; /** 年月 */
@Convert(converter = YearMonthIntegerAttributeConverter.class)
@Column(name = "year_month")
private YearMonth yearMonth; }

1.3、创建 jpa 查询

package com.chayiges;

import org.springframework.data.jpa.repository.JpaRepository;

import java.time.YearMonth;
import java.util.UUID; /**
* 学生表的jap查询
*
* @author chayiges
*/
public interface Students extends JpaRepository<Student, UUID> { /**
* 根据年月查询学生表
* @param yearMonth 年月
* @return 学生表
*/
List<Student> findByYearMonth(YearMonth yearMonth); }

1.4、测试

package jp.chayiges;

import lombok.RequiredArgsConstructor;
import org.junit.jupiter.api.Test; import java.time.YearMonth;
import java.util.UUID;
import java.util.List; /**
* jap查询测试
*
* @author chayiges
*/
@RequiredArgsConstructor
public class StudentJPAUnitTests { /** 实体类到数据库表的转换器 */
final YearMonthIntegerAttributeConverterauto yearMonthIntegerAttributeConverterauto; /** 学生表 jpa */
final Students students;   /**
* テスト
*/
@Test
void findByYearMonthTest() { YearMonth yearMonth = YearMonth.of(2022, 7);
// 创建学生对象
Student stu = new Student("a57988c3-1711-4288-9623-9e7c177ff078",
"孙汐", yearMonth);
// 调用 jpa 方法进行保存,保存的时候会进入自定义的Convert实现类中进行实体类属性值到数据
// 库中对应字段值的转换
this.students.save(stu); // 调用 jpa 方法查询
List<Student> studentList = this.students.findByYearMonth(yearMonth); }
}

1.5、创建了错误的 jpa 方法

package com.chayiges;

import org.springframework.data.jpa.repository.JpaRepository;

import java.time.YearMonth;
import java.util.UUID; /**
* 学生表的jap查询
*
* @author chayiges
*/
public interface Students extends JpaRepository<Student, UUID> { /**
* 根据年月查询学生表
* @param yearMonth 年月
* @return 学生表
*/
List<Student> findByYearMonth(Integer integer); }

1.6、错误的 jpa 方法的测试

package jp.chayiges;

import lombok.RequiredArgsConstructor;
import org.junit.jupiter.api.Test; import java.time.YearMonth;
import java.util.UUID;
import java.util.List; /**
* jap查询测试
*
* @author chayiges
*/
@RequiredArgsConstructor
public class StudentJPAUnitTests { /** 实体类到数据库表的转换器 */
final YearMonthIntegerAttributeConverterauto yearMonthIntegerAttributeConverterauto; /** 学生表jpa */
final Students students; /**
* テスト
*/
@Test
void findByYearMonthTest() { YearMonth yearMonth = YearMonth.of(2022, 7);
// 创建学生对象
Student stu = new Student("a57988c3-1711-4288-9623-9e7c177ff078",
"孙汐", yearMonth);
// 调用 jpa 方法进行保存,保存的时候会进入自定义的Convert实现类中进行实体类属性值到数据
// 库中对应字段值的转换
this.students.save(stu); // 调用 jpa 方法查询,会抛出 InvalidDataAccessApiUsageException 异常
List<Student> studentList = this.students.findByYearMonth(this
.yearMonthIntegerAttributeConverterauto
.convertToDatabaseColumn(yearmonth));
}
}

注意:此处查询年月的时候用的是实体类中 YearMonth 类型,并不是转换到数据库中的 Integer 类型

至于数据保存到数据库中确实是 Integer 类型,但是查询的时候依然要使用实体类中属性的类型这个问题,本人也不知其中缘由,有懂的大佬麻烦指出

对应到本人CSDN的博客

@Convert 注解在jpa中进行查询的注意事项的更多相关文章

  1. JPA 中注解的作用

    JPA全称Java Persistence API.JPA通过JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中.        JPA由EJB 3.0软件专家 ...

  2. 使用JPA中@Query 注解实现update 操作

    spring使用jpa进行update操作主要有两种方式: 1.调用保存实体的方法 1)保存一个实体:repository.save(T entity) 2)保存多个实体:repository.sav ...

  3. JPA中EntityListeners注解的使用

    使用场景 EntityListeners在jpa中使用,如果你是mybatis是不可以用的 它的意义 对实体属性变化的跟踪,它提供了保存前,保存后,更新前,更新后,删除前,删除后等状态,就像是拦截器一 ...

  4. Spring data JPA中使用Specifications动态构建查询

    有时我们在查询某个实体的时候,给定的条件是不固定的,这是我们就需要动态 构建相应的查询语句,在JPA2.0中我们可以通过Criteria接口查询,JPA criteria查询.相比JPQL,其优势是类 ...

  5. Spring Data JPA中的动态查询 时间日期

    功能:Spring Data JPA中的动态查询 实现日期查询 页面对应的dto类private String modifiedDate; //实体类 @LastModifiedDate protec ...

  6. spring boot JPA中实体类常用注解

    spring boot jpa中的注解很多,参数也比较多.没必要全部记住,但是经常查看官方文档也比较麻烦,记录一下一些常用的注解.通过一些具体的例子来帮助记忆. @Entity @Table(name ...

  7. 【hql】spring data jpa中 @Query使用hql查询 问题

    spring data jpa中 @Query使用hql查询 问题 使用hql查询, 1.from后面跟的是实体类 不是数据表名 2.字段应该用实体类中的字段 而不是数据表中的属性 实体如下 hql使 ...

  8. jpa中使用Query判断条件查询

    jpa中使用Query判断条件查询 @Query(value = " select m.* from mining_area as m " + " where 1 = 1 ...

  9. JPA中建立数据库表和实体间映射小结

    在JPA中,映射数据库表和实体的时候,需要注意一些细节如下, 实体类要用@Entity的注解: 要用 @Id 来注解一个主键: 如果跟数据库相关联,要用@Table注解相关数据库表: 实体类中字段需要 ...

随机推荐

  1. Caused by: java.lang.Exception: No native library is found for os.name=Mac and os.arch=aarch64. path=/org/sqlite/native/Mac/aarch64

    编译项目报错: Caused by: java.lang.Exception: No native library is found for os.name=Mac and os.arch=aarch ...

  2. 新作!分布式系统韧性架构压舱石OpenChaos

    摘要:本文首先以现今分布式系统的复杂性和稳定性的需求引出混沌工程概念,并阐述了OpenChaos在传统混沌工程上的优化与创新. 背景 随着Serverless,微服务(含服务网格)与越来越多的容器化架 ...

  3. data:image字符转byte[]

    var data = "data:image/bmp;base64,Qk3aHwAAAAAAADYAAAAoAAAAZAAAABsAAAABABgAAAAAAKQfAAAAAQAAAAEAA ...

  4. ID为XXXX的进程当前未运行

    项目文件夹下,有个.vs的文件夹,删除掉,然后重新打开项目就ok了. 或者: 在启动项目根目录下用文本编辑器打开Web项目下的{X}.csproj文件,然后查找 <WebProjectPrope ...

  5. MyCat应用实战

    下载Mycat https://github.com/MyCATApache/Mycat-Server/releases Mycat基础分库 基础配置 修改server.xml <user na ...

  6. Solon 1.8.0 发布,云原生微服务开发框架

    相对于 Spring Boot 和 Spring Cloud 的项目 启动快 5 - 10 倍 qps 高 2- 3 倍 运行时内存节省 1/3 ~ 1/2 打包可以缩小到 1/2 ~ 1/10(比如 ...

  7. 图的连通性--Tarjan算法

    一些概念 无向图: 连通图:在无向图中,任意两点都直接或间接连通,则称该图为连通图.(或者说:任意两点之间都存在可到达的路径) 连通分量: G的 最大连通子图 称为G的连通分量. 有向图 (ps.区别 ...

  8. c++ 树状数组

    关于树状数组 树状数组,即 Binary Indexed Tree ,主要用于维护查询前缀和 属于 log 型数据结构 和线段树比较 都是 log 级别 树状数组常数.耗费的空间.代码量都比线段树小 ...

  9. Hash表、 继承

    Hash表 我们来了解什么是Hash表?? 要想知道什么是哈希表,那得先了解哈希函数 二叉平衡树 红黑树 B B+树,它们的查找都是先从根节点进行查找,从节点取出数据或索引与查找值进行比较.那么,有没 ...

  10. 喜提JDK的BUG一枚!多线程的情况下请谨慎使用这个类的stream遍历。

    你好呀,我是歪歪. 前段时间在 RocketMQ 的 ISSUE 里面冲浪的时候,看到一个 pr,虽说是在 RocketMQ 的地盘上发现的,但是这个玩意吧,其实和 RocketMQ 没有任何关系. ...