gpt4 book ai didi

java - JPA:向多对多添加新条目需要很长时间

转载 作者:行者123 更新时间:2023-11-29 09:56:38 25 4
gpt4 key购买 nike

我在多对多关系中添加新条目时遇到问题,因为列表很大。例如:

Item item = new Item(1);
Category cat = dao.find(1, Category.class);
List<Category> list = new ArrayList<>();
list.add(cat);
item.setCategoryList(list);
cat.getItemList().add(item);

问题在于 Category Itens 列表很大,有很多 itens,因此执行 cat.getItemList() 需要很长时间。我到处寻找添加多对多条目的正确方法,都表明需要这样做。有人可以帮忙吗?

编辑:一些上下文:我用标签组织我的 itens,因此 1 个项目可以有多个标签,1 个标签可以有多个 itens,时间已经过去,现在我有带有很多 itens 的标签(> 5.000),现在当我保存时带有这些标签之一的新项目需要很长时间,我已经调试了我的代码,发现大部分延迟都在 cat.getItensList() 行中,这是有道理的,因为它有一个广泛的项目列表。我已经搜索了很多如何做到这一点,每个人都说在多对多情况下保存条目的正确方法是添加到关系两侧的列表中,但如果一侧很大,调用 getItensList() 将它们加载到上下文中会花费很多时间。我正在寻找一种方法来保存引用标签的项目,而不加载该标签的所有项目。

编辑2:我的类(class):项目:

@Entity
@Table(name = "transacao")
@XmlRootElement
public class Transacao implements Serializable {
@ManyToMany(mappedBy = "transacaoList")
private List<Tagtransacao> tagtransacaoList;
...(other stuff)
}

标签:

@Entity
@Table(name = "tagtransacao")
@XmlRootElement
public class Tagtransacao implements Serializable {
@JoinTable(name = "transacao_has_tagtransacao", joinColumns = {
@JoinColumn(name = "tagtransacao_idTagTransacao", referencedColumnName = "idTagTransacao")}, inverseJoinColumns = {
@JoinColumn(name = "transacao_idTransacao", referencedColumnName = "idTransacao")})
@ManyToMany
private List<Transacao> transacaoList;
...(other stuff)
}

编辑3:我要解决的问题:正如 Ariel Kohan 所回答的,我尝试执行 NativeQuery 来插入关系:

  Query query = queryDAO.criarNativeQuery("INSERT INTO " + config.getNomeBanco() + ".`transacao_has_tagtransacao` "
+ "(`transacao_idTransacao`, `tagtransacao_idTagTransacao`) VALUES (:idTransacao, :idTag);");
query.setParameter("idTransacao", transacao.getIdTransacao());
query.setParameter("idTag", tag.getIdTagTransacao());

我能够将 que 查询的时间从 10 秒减少到 300 毫秒,令人印象深刻。最后,对于我的项目来说,它已经在运行了,而不是创建一个代表多对多关系的新类,这对我的项目来说更好。感谢所有尝试帮助的人\o/

最佳答案

在这种情况下,我会阻止您的代码加载内存中的项目列表。

为此,我可以考虑两种选择:

使用 @Modyfing 查询将项目直接插入数据库中。

[推荐用于您想避免更改模型的情况]

您可以尝试使用普通 JPQL 创建查询,但根据您的模型,您可能需要使用 native 查询。使用 native 查询将是这样的:

@Query(value = "insert into ...", nativeQuery = true)
void addItemToCategory(@Param("param1") Long param1, ...);

创建此查询后,您将需要更新代码,删除在内存中加载对象的部分,并添加调用插入语句的部分。

[Update] As you mentioned in a comment, doing this improved your performance from 10s to 300milis.

<小时/>

修改您的实体,以便将 @ManyToMany 替换为 @OneToMany 关系

此解决方案的想法是用中间实体 RelationAB 替换实体 AB 之间的多对多关系。我认为你可以通过两种方式做到这一点:

  1. 仅将 RelationAB 中的 A 和 B 的 ID 保存为复合键(当然,您可以添加其他字段,例如日期或任何您想要的字段)。
  2. 将自动生成的 Id 添加到 RelationAB,并将 A 和 B 添加为 RelationAB 实体中的其他字段。

我使用第一个选项做了一个示例(您会看到这些类不是公共(public)的,这只是因为为了简单起见,我决定在单个文件中执行它。当然,您可以在多个文件中执行它文件和公共(public)类(如果需要):

实体 A 和 B:

@Entity
class EntityA {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

public EntityA() {
}

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

}

@Entity
class EntityB {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;


public EntityB() {
}

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

}

RelationABEntityRelationABId:

@Embeddable
class RelationABId implements Serializable {
private Long entityAId;
private Long entityBId;

public RelationABId() {
}

public RelationABId(Long entityAId, Long entityBId) {
this.entityAId = entityAId;
this.entityBId = entityBId;
}

public Long getEntityAId() {
return entityAId;
}

public void setEntityAId(Long entityAId) {
this.entityAId = entityAId;
}

public Long getEntityBId() {
return entityBId;
}

public void setEntityBId(Long entityBId) {
this.entityBId = entityBId;
}
}

@Entity
class RelationABEntity {

@EmbeddedId
private RelationABId id;

public RelationABEntity() {
}

public RelationABEntity(Long entityAId, Long entityBId) {
this.id = new RelationABId(entityAId, entityBId);
}

public RelationABId getId() {
return id;
}

public void setId(RelationABId id) {
this.id = id;
}
}

我的存储库:

@Repository
interface RelationABEntityRepository extends JpaRepository<RelationABEntity, RelationABId> {

}

@Repository
interface ARepository extends JpaRepository<EntityA, Long> {


}

@Repository
interface BRepository extends JpaRepository<EntityB, Long> {

}

测试:

@RunWith(SpringRunner.class)
@DataJpaTest
public class DemoApplicationTest {

@Autowired RelationABEntityRepository relationABEntityRepository;
@Autowired ARepository aRepository;
@Autowired BRepository bRepository;


@Test
public void test(){
EntityA a = new EntityA();
a = aRepository.save(a);
EntityB b = new EntityB();
b = bRepository.save(b);

//Entities A and B in the DB at this point

RelationABId relationABID = new RelationABId(a.getId(), b.getId());

final boolean relationshipExist = relationABEntityRepository.existsById(relationABID);
assertFalse(relationshipExist);

if(! relationshipExist){
RelationABEntity relation = new RelationABEntity(a.getId(), b.getId());
relationABEntityRepository.save(relation);
}

final boolean relationshipExitNow = relationABEntityRepository.existsById(relationABID);
assertTrue(relationshipExitNow);
/**
* As you can see, modifying your model you can create relationships without loading big list and without complex queries.
*/
}
}

上面的代码解释了处理此类事情的另一种方法。当然,您可以根据自己的实际需要进行修改。

希望这有帮助:)

关于java - JPA:向多对多添加新条目需要很长时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53706999/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com