小编And*_*ver的帖子

JPA:getReference()与仅具有ID的新“模拟”对象?

我想知道通过不使用代理对象而是通过创建新对象并手动设置ID来将实体与子实体相关联是否可行?像这样?

  @Transactional
    public void save(@NonNull String name, @NonNull Long roleId) {
        User user = new User();
        user.setName(name);
        Role role = new Role(); role.setRoleId(roleId);
        // Instead of: 
        // roleRepository.getOne(roleId);
        user.setRole(role);
        userRepository.save(user);
    }
Run Code Online (Sandbox Code Playgroud)

我知道,可以通过调用smth来实现这一公认且有据可查的方法。喜欢:

em.getReference(Role.class, roleId) ;
Run Code Online (Sandbox Code Playgroud)

或者如果使用Spring Data

roleRepository.getOne(roleId);
Run Code Online (Sandbox Code Playgroud)

或休眠方式:

session.load(Role.class, roleId)
Run Code Online (Sandbox Code Playgroud)

因此,问题是,如果他通过欺骗JPA提供程序并使用带有集合ID的新对象来实现此技巧,将会面临什么样的严重后果?请注意,执行getOne()的唯一原因是将新创建的实体与现有实体相关联。然而,角色模拟对象并未得到管理,也不用担心丢失任何数据。它只是做连接两个实体的工作。

从Hibernate文档中:

getReference()获得对该实体的引用。状态可以初始化也可以不初始化。如果该实体已经与当前正在运行的Session关联,则返回该引用(是否已加载)。如果该实体未在当前会话中加载并且该实体支持代理生成,则会生成并返回未初始化的代理,否则从数据库加载该实体并返回。

因此,在测试之后,我发现它基本上甚至没有命中数据库来检查ID的存在,并且如果违反FK约束,则save()在提交时将失败。它只需要附加依赖项即可自动关联(RoleRepository)。

那么,如果我的情况如此简单,为什么我应该通过调用getOne()而不是使用new创建的模拟对象来获取此代理?这种方法可能在什么时候出问题?

谢谢您的澄清。

编辑:

Hibernate / JPA,仅在@OneToOne关联上设置id时保存一个新实体

此相关主题无法回答问题。我在问为什么调用JPA的API getReference()更好,如果我采用这种用给定的ID和new运算符创建新的“模拟”对象的做法,对我来说会发生什么错误?

java spring hibernate

5
推荐指数
0
解决办法
313
查看次数

Spring Boot 测试:根据活动配置文件在测试中执行不同的 sql 脚本?

Spring Boot Test 是否可以根据活动配置文件设置 sql 脚本的条件执行?我的意思是,我对存储库进行了集成测试,并使用了一些 @sql 注释,例如:

@Sql(scripts = "/scripts/entity_test_clear.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD)
Run Code Online (Sandbox Code Playgroud)
  • 对于配置文件 h2,我想执行entity_test_clear.sql

  • 对于配置文件 mysql 我想执行entity_test_clear_mysql.sql

原因是我对这些数据库使用了不同的语法,尤其是这个:

  • ALTER TABLE organisation ALTER COLUMN org_id RESTART WITH 1;
  • ALTER TABLE organisation AUTO_INCREMENT = 1;

Mysql 不理解语法 #1,而 h2 不理解语法 #2(尽管设置了 mysql 模式,如 MODE=MYSQL)

默认情况下,我使用 h2 进行 IT 测试,但在一些罕见的情况下,我也想检查一切是否与 mysql 一起顺利运行。

PS我当然可以尝试一个直接的解决方案,@Profile并对h2和mysql的每个测试进行硬编码,但它与测试中的大量代码重复相结合,我想避免这种情况。

编辑: 测试用例如下所示:

@RunWith(SpringRunner.class)
@DataJpaTest
@AutoConfigureTestDatabase(replace= AutoConfigureTestDatabase.Replace.NONE)
public class EntityRepositoryTestIT {

    @Autowired
    private EntityRepository entityRepository;

@Test
@Sql(scripts = {"/scripts/entity_test_data.sql", "/scripts/entity_test_data_many.sql"}, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
@Sql(scripts = …
Run Code Online (Sandbox Code Playgroud)

java sql spring spring-boot

5
推荐指数
1
解决办法
9245
查看次数

Spring Data JPA,在 CrudRepository 接口中参数化@EntityGraph

Spring Data JPA 是否可以做某事。像这样:

public interface UserDao extends CrudRepository<User, Long> {

@EntityGraph(value = :graphName, type = EntityGraph.EntityGraphType.LOAD)
    @Query(value = "SELECT DISTINCT u FROM User u")
    List<User> findAllWithDetailsByGraphName(@Param(value="graphName") String graphName);

}
Run Code Online (Sandbox Code Playgroud)

能够在运行时将 graphName 传递给方法并使用一组需要的集合调用负载?此构造不起作用,产生编译时错误。任何围绕它的游戏也失败了......

所以,我在 User 类中有多个集合,我想根据条件加载它们;

@Entity
@Table(name="user")
@NamedEntityGraphs({
        @NamedEntityGraph(name = "User.details", attributeNodes = {
                @NamedAttributeNode("phones"), @NamedAttributeNode("emails"), @NamedAttributeNode("pets")}),
        @NamedEntityGraph(name = "User.phones", attributeNodes =
                {@NamedAttributeNode("phones")}),
        @NamedEntityGraph(name = "User.emails", attributeNodes =
                {@NamedAttributeNode("emails")}),
        @NamedEntityGraph(name = "User.pets", attributeNodes =
                {@NamedAttributeNode("pets")})
})
public class User {
    @Id
    @GeneratedValue(strategy= GenerationType.AUTO, generator="native")
    @GenericGenerator(name = "native", strategy = …
Run Code Online (Sandbox Code Playgroud)

spring jpa entitygraph

3
推荐指数
1
解决办法
2000
查看次数

标签 统计

spring ×3

java ×2

entitygraph ×1

hibernate ×1

jpa ×1

spring-boot ×1

sql ×1