I have an entity with string id:
@Table
@Entity
public class Stock {
@Id
@Column(nullable = false, length = 64)
private String index;
@Column(nullable = false)
private Integer price;
}
And JpaRepository for it:
public interface StockRepository extends JpaRepository<Stock, String> {
}
When I call stockRepository::findAll
, I have N + 1
problem:
logs are simplified
select s.index, s.price from stock s
select s.index, s.price from stock s where s.index = ?
The last line from the quote calls about 5K times (the size of the table). Also, when I update prices, I do next:
stockRepository.save(listOfStocksWithUpdatedPrices);
In logs I have N
inserts.
I haven't seen similar behavior when id was numeric.
P.S. set id's type to numeric is not the best solution in my case.
UPDATE1:
I forgot to mention that there is also Trade
class that has many-to-many relation with Stock
:
@Table
@Entity
public class Trade {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
@Column
@Enumerated(EnumType.STRING)
private TradeType type;
@Column
@Enumerated(EnumType.STRING)
private TradeState state;
@MapKey(name = "index")
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "trade_stock",
joinColumns = { @JoinColumn(name = "id", referencedColumnName = "id") },
inverseJoinColumns = { @JoinColumn(name = "stock_index", referencedColumnName = "index") })
private Map<String, Stock> stocks = new HashMap<>();
}
UPDATE2:
I added many-to-many relation for the Stock
side:
@ManyToMany(cascade = CascadeType.ALL, mappedBy = "stocks") //lazy by default
Set<Trade> trades = new HashSet<>();
But now it left joins trades (but they're lazy), and all trade's collections (they are lazy too). However, generated Stock::toString
method throws LazyInitializationException
exception.