弱投影模型
介绍
数据模型可能很棘手。 建模可能会更加困难。 有时候,应该放入数据库表中的信息不一定是我们要在每段代码中使用的信息。
和其他许多次一样,Spring来了。 一个称为投影的小功能可以帮助我们在普通界面中仅用几行数据映射数据。
在本文中,我们将看到一个有关如何使用投影的简单示例。
基础
好的,让我们设置场景。 假设我们有以下实体:
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table
@EqualsAndHashCode(doNotUseGetters = true)
@ToString(doNotUseGetters = true)
public class User implements Serializable {@Id@SequenceGenerator(name = "user_seq", sequenceName = "user_seq")@GeneratedValue(strategy = GenerationType.IDENTITY, generator = "user_seq")private Long id;@Basicprivate String username;@Basicprivate String salt;@Basicprivate String password;@Basicprivate String firstName;@Basicprivate String lastName;
}
此处的一些解释可能会有所帮助:让我们看一下注释。 老实说,我很懒,所以Lombok就在我的小巷旁。 Lombok为我们提供了一种很好的声明方式,表明我们需要:
- 一个不错的生成器接口来创建bean(
@Builder
) - 获取器和设置器(
@Data
) - 默认构造函数(
@NoArgsConstructor
) - 一个带有所有字段参数的构造函数(
@AllArgsConstructor
) -
equals()
和hashCode()
,但是请使用字段,而不是getters(@EqualsAndHashCode(doNotUseGetters = true)
) -
toString()
; 再次使用字段(@ToString(doNotUseGetter = true)
)
其余的注释( @Entity
和@Table
)是旧的JPA。
是的,所以,我们有一个很好的实体。 怎么了
以传统方式获取数据
让我们看一下这个存储库:
@Repository
public interface UserRepository extends JpaRepository<User, Long> {}
上面的代码为我们提供了最少的CRUD方法集。 一个是getOne(Long id)
。 好,不是吗?
好吧,正确的答案必须是:这取决于! 为什么? 因为这将返回整个实体,包括盐和哈希密码。 这是非常敏感的信息。 特别是盐永远不应该被外界吸收。
为了从生成的实体中获取此信息,我们将不得不做大量的手工工作。 只是从我的头开始,我们应该:*创建一个新bean *实现一个映射器以从我们的实体获取到该新bean *确保每次我们处理该实体时,我们都将其映射*在实现该实体时会感到头疼也可能有多种结果。
退还最低要求
值得庆幸的是,Spring可以确保这一天的安全。 一个叫做Projections的小功能让我们以声明的方式定义映射。 这样的接口看起来像这样:
public interface UserProjection {@Value("#{target.getUsername()}")String getUsername();@Value("#{target.getFirstName()}")String getFirstName();@Value("#{target.getLastName()}")String getLastName();
}
Spring将用我们当前正在处理的实体替换target
。 换句话说, target
将是User
的实例。
我们现在要做的唯一的事情是这样的:
@Repository
public interface UserRepository extends JpaRepository<User, Long> {UserProjection findById(Long id);List<UserProjection> findAllUser();
}
现在,每次调用findById()
,我们都会获得UserProjection
的实例。 我们的盐或密码哈希不能泄漏! 更好的是,我们可以对具有多个结果的方法使用相同的过程。
结论
使用Spring Projections,我们可以节省很多代码和麻烦。 @Value()
定义可以根据需要变得复杂。 例如,在我当前的项目中,当我们将“有趣的”旧数据库设计映射到更简单的数据模型中时,这为我的团队节省了很多样板代码。
如果您想尝试一下,可以在GitHub上找到一个简单的示例应用程序。
翻译自: https://www.javacodegeeks.com/2018/01/power-data-model-projections.html
弱投影模型