Java 用JPA实现数据库一级缓存

Java 用JPA实现数据库一级缓存,java,spring,spring-boot,spring-data-jpa,spring-data,Java,Spring,Spring Boot,Spring Data Jpa,Spring Data,我有以下设置(未测试),因为我担心这将打破。在签入LDAP之前,我想在数据库中实现某种一级缓存查找 (1)如何在服务代码中循环表/getUserEmail,恐怕会有多行来自数据库。如果没有,如何预防。 (2)如何改进或使其成为傻瓜。 我对JPA/Spring boot一般来说是新手,所以请帮助我 实体 @Entity @Table(name = "userEmailCache") public class userEmailCacheEntity { @Id

我有以下设置(未测试),因为我担心这将打破。在签入LDAP之前,我想在数据库中实现某种一级缓存查找

(1)如何在服务代码中循环表/getUserEmail,恐怕会有多行来自数据库。如果没有,如何预防。 (2)如何改进或使其成为傻瓜。

我对JPA/Spring boot一般来说是新手,所以请帮助我

实体

@Entity
@Table(name = "userEmailCache")
public class userEmailCacheEntity {


    @Id
    @Column(unique = true)
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String userEmail;
    private String userId;
// getter and setters redacted
@Repository

    public interface userEmailCacheEntityRepository extends JpaRepository<userEmailCacheEntity, Long>  {
    
        @Query(value="SELECT "
                + "userEmail "
                + "FROM userEmailCache "
                + "WHERE userId = :param01 ")
        String getUserEmail(@Param("param01") String param01);
    }
存储库

@Entity
@Table(name = "userEmailCache")
public class userEmailCacheEntity {


    @Id
    @Column(unique = true)
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String userEmail;
    private String userId;
// getter and setters redacted
@Repository

    public interface userEmailCacheEntityRepository extends JpaRepository<userEmailCacheEntity, Long>  {
    
        @Query(value="SELECT "
                + "userEmail "
                + "FROM userEmailCache "
                + "WHERE userId = :param01 ")
        String getUserEmail(@Param("param01") String param01);
    }

Java按照惯例使用CamelCase和大写的类名,所以我改变了这一点

您不需要在
@Id
上使用
@Column(unique=true)
-这意味着它是主键,并且必须是唯一的

@Entity
@Table(name = "userEmailCache")
public class UserEmailCacheEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String userEmail;
    private String userId;
// getter and setters redacted
}
那么你说
userId
不是唯一的?我认为这有点用词不当,因为ID应该用来识别事物。无论如何,您可能希望确保在数据库中的
userId
列上有一个索引,以加快搜索速度

不过,您确实弄错了返回类型。因为您说过每个
用户ID可以有多封电子邮件,所以您需要返回一个列表:

@Repository
public interface UserEmailCacheEntityRepository 
        extends JpaRepository<UserEmailCacheEntity, Long>  {

    @Query(value="SELECT "
            + "userEmail "
            + "FROM userEmailCache "
            + "WHERE userId = :uid ")
    List<String> getUserEmails(@Param String uid);

}
@存储库
公共接口UserEmailCacheEntityRepository
扩展JPA假设{
@查询(value=“选择”
+“用户电子邮件”
+“来自userEmailCache”
+“其中userId=:uid”)
列出getUserEmails(@Param String uid);
}
然后还需要处理包含多个条目的结果:

@Autowired
userEmailCacheEntityRepository repo;

//check in database and get email
List<String> strEmails = repo.getUserEmails(userId);

//if not found in database
if (strEmails.isEmpty()) {
    //fetch email from LDAP/Active Directory
    String ldapMail = retrieve();
} else {
LOG.info("[I] Found in DB {} results for {}: {}", strEmail.size(), userId, strEmail);
}

//save in Database
UserEmailCacheEntity file = new userEmailCacheEntity();
file.setUserEmail(ldapMail);
file.setUserId(userId);
repo.save(file);
@Autowired
userEmailCacheEntityRepository回购;
//签入数据库并获取电子邮件
List strEmails=repo.getUserEmails(userId);
//如果在数据库中找不到
if(strEmails.isEmpty()){
//从LDAP/Active Directory获取电子邮件
字符串ldapMail=retrieve();
}否则{
LOG.info({}:{},strEmail.size(),userId,strEmail的DB{}结果中找到[I];
}
//保存在数据库中
UserEmailCacheEntity文件=新的UserEmailCacheEntity();
setUserEmail(ldapMail)文件;
setUserId(userId);
保存(文件);
我无法告诉您如何处理多封返回的电子邮件,因为我不知道您在用它们做什么(尽管这种设计似乎很奇怪)


你为什么称你的新实体为“文件”?它不是文件,不是吗?

它不是文件。我使用以下函数绕过可选的findFirst1ByUserIdOrderByEmailAsc(字符串userId);