Issue
I updated some files to set up the connection with the MySQ database, after that the program won't start.
Full errors list:
2022-08-23 19:50:54.927 ERROR 25220 --- [ restartedMain] j.LocalContainerEntityManagerFactoryBean : Failed to initialize JPA EntityManagerFactory: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags: [com.bn.market.entities.User.productList, com.bn.market.entities.User.roles]
2022-08-23 19:50:54.927 WARN 25220 --- [ restartedMain] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags: [com.bn.market.entities.User.productList, com.bn.market.entities.User.roles]
2022-08-23 19:50:54.929 INFO 25220 --- [ restartedMain] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated...
2022-08-23 19:50:54.935 INFO 25220 --- [ restartedMain] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed.
2022-08-23 19:50:54.936 INFO 25220 --- [ restartedMain] o.apache.catalina.core.StandardService : Stopping service [Tomcat]
2022-08-23 19:50:54.951 INFO 25220 --- [ restartedMain] ConditionEvaluationReportLoggingListener :
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2022-08-23 19:50:54.976 ERROR 25220 --- [ restartedMain] o.s.boot.SpringApplication : Application run failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags: [com.bn.market.entities.User.productList, com.bn.market.entities.User.roles]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1804) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:620) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1154) ~[spring-context-5.3.22.jar:5.3.22]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:908) ~[spring-context-5.3.22.jar:5.3.22]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) ~[spring-context-5.3.22.jar:5.3.22]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147) ~[spring-boot-2.7.3.jar:2.7.3]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:734) ~[spring-boot-2.7.3.jar:2.7.3]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:408) ~[spring-boot-2.7.3.jar:2.7.3]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:308) ~[spring-boot-2.7.3.jar:2.7.3]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) ~[spring-boot-2.7.3.jar:2.7.3]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295) ~[spring-boot-2.7.3.jar:2.7.3]
at com.bn.market.MarketApplication.main(MarketApplication.java:10) ~[classes/:na]
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:577) ~[na:na]
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) ~[spring-boot-devtools-2.7.3.jar:2.7.3]
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags: [com.bn.market.entities.User.productList, com.bn.market.entities.User.roles]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:421) ~[spring-orm-5.3.22.jar:5.3.22]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396) ~[spring-orm-5.3.22.jar:5.3.22]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:341) ~[spring-orm-5.3.22.jar:5.3.22]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1863) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1800) ~[spring-beans-5.3.22.jar:5.3.22]
... 19 common frames omitted
Caused by: org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags: [com.bn.market.entities.User.productList, com.bn.market.entities.User.roles]
at org.hibernate.loader.plan.exec.internal.AbstractLoadQueryDetails.generate(AbstractLoadQueryDetails.java:193) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
at org.hibernate.loader.plan.exec.internal.EntityLoadQueryDetails.<init>(EntityLoadQueryDetails.java:85) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
at org.hibernate.loader.plan.exec.internal.BatchingLoadQueryDetailsFactory.makeEntityLoadQueryDetails(BatchingLoadQueryDetailsFactory.java:64) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
at org.hibernate.loader.entity.plan.AbstractLoadPlanBasedEntityLoader.<init>(AbstractLoadPlanBasedEntityLoader.java:97) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
at org.hibernate.loader.entity.plan.AbstractLoadPlanBasedEntityLoader.<init>(AbstractLoadPlanBasedEntityLoader.java:112) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
at org.hibernate.loader.entity.plan.EntityLoader.<init>(EntityLoader.java:117) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
at org.hibernate.loader.entity.plan.EntityLoader.<init>(EntityLoader.java:30) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
at org.hibernate.loader.entity.plan.EntityLoader$Builder.byUniqueKey(EntityLoader.java:82) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
at org.hibernate.loader.entity.plan.EntityLoader$Builder.byPrimaryKey(EntityLoader.java:75) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
at org.hibernate.loader.entity.plan.AbstractBatchingEntityLoaderBuilder.buildNonBatchingLoader(AbstractBatchingEntityLoaderBuilder.java:30) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
at org.hibernate.loader.entity.BatchingEntityLoaderBuilder.buildLoader(BatchingEntityLoaderBuilder.java:61) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
at org.hibernate.persister.entity.AbstractEntityPersister.createEntityLoader(AbstractEntityPersister.java:2689) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
at org.hibernate.persister.entity.AbstractEntityPersister.createEntityLoader(AbstractEntityPersister.java:2711) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
at org.hibernate.persister.entity.AbstractEntityPersister.generateDelayedEntityLoader(AbstractEntityPersister.java:4464) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
at org.hibernate.internal.util.collections.LazyIndexedMap.lockedComputeIfAbsent(LazyIndexedMap.java:77) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
at org.hibernate.internal.util.collections.LazyIndexedMap.computeIfAbsent(LazyIndexedMap.java:63) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
at org.hibernate.persister.entity.EntityLoaderLazyCollection.getOrBuildByLockMode(EntityLoaderLazyCollection.java:34) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
at org.hibernate.persister.entity.AbstractEntityPersister.getLoaderByLockMode(AbstractEntityPersister.java:4455) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
at org.hibernate.persister.entity.AbstractEntityPersister.createLoaders(AbstractEntityPersister.java:4442) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
at org.hibernate.persister.entity.AbstractEntityPersister.postInstantiate(AbstractEntityPersister.java:4416) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
at org.hibernate.metamodel.internal.MetamodelImpl.initialize(MetamodelImpl.java:257) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:319) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:471) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1498) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:58) ~[spring-orm-5.3.22.jar:5.3.22]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365) ~[spring-orm-5.3.22.jar:5.3.22]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409) ~[spring-orm-5.3.22.jar:5.3.22]
... 23 common frames omitted
I updated my User entity(connection with DB roles works):
@Entity
@Table(name = "user", uniqueConstraints = @UniqueConstraint(columnNames = "email"))
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "first_name")
private String firstName;
@Column(name = "last_name")
private String lastName;
private String email;
private String password;
@Column(name = "amount_of_money")
private int amountOfMoney;
@ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinTable(name = "users_roles",
joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id"))
private Collection<Role> roles;
@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH, CascadeType.DETACH},
fetch = FetchType.EAGER)
@JoinTable(
name = "product_list",
joinColumns = @JoinColumn(name = "user_id",referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(name = "product_id",referencedColumnName = "id")
)
private Collection<Product> productList;
public User() {
}
public User(String firstName, String lastName, String email, String password, Collection<Role> roles) {
super();
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
this.password = password;
this.roles = roles;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getAmountOfMoney() {
return amountOfMoney;
}
public void setAmountOfMoney(int amountOfMoney) {
this.amountOfMoney = amountOfMoney;
}
public Collection<Role> getRoles() {
return roles;
}
public void setRoles(Collection<Role> roles) {
this.roles = roles;
}
public Collection<Product> getProductList() {
return productList;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
", email='" + email + '\'' +
", roles=" + roles +
'}';
}
}
Added this file:
@Entity
@Table(name = "products")
public class Product {
@Column
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Column
private String name;
@Column
private int price;
@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH, CascadeType.DETACH},
fetch = FetchType.EAGER)
@JoinTable(
name = "product_list",
joinColumns = @JoinColumn(name = "product_id"),
inverseJoinColumns = @JoinColumn(name = "user_id")
)
private Collection<User> userList;
public Product() {
}
public Product(String name, int price) {
this.name = name;
this.price = price;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public Collection<User> getUserList() {
return userList;
}
public void addUserToBuyerList(User user) throws Exception {
if (user.getAmountOfMoney() < price)
throw new ArithmeticException("Not enough money!");
else
user.setAmountOfMoney(user.getAmountOfMoney() - price);
if (userList == null)
userList = new ArrayList<>();
userList.add(user);
}
@Override
public String toString() {
return "id=" + id +
", name='" + name + '\'' +
", price=" + price;
}
}
Added repository interface for product
@Repository
public interface UserRepository extends JpaRepository<User, Long>{
User findByEmail(String email);
List<User> findAll();
User getUserById(long id);
}
Service interface file:
public interface ProductService {
}
And service implementation file:
@Service
public class ProductServiceImpl implements ProductService {
@Autowired
ProductRepository productRepository;
}
Before updating Java code I created database with that code:
CREATE TABLE market_db.products (
id bigint NOT NULL AUTO_INCREMENT,
name varchar(15),
price int,
PRIMARY KEY (id)
);
CREATE TABLE market_db.product_list (
user_id bigint,
product_id bigint NOT NULL,
PRIMARY KEY (user_id, product_id),
FOREIGN KEY (user_id) REFERENCES market_db.user(id),
FOREIGN KEY (product_id) REFERENCES market_db.products(id));
I think in pom file everything is ok because the program has been working. But after adding those new features something happened
Solution
This problem is occurring because fetching Users you are fetching the two collections together, and then could lead to a Cartesian product, bags don't have order so Hibernate will have problems to map the right columns to right entities, this could be solved using a Set as a collection instead, would is not the preferred, or you can add a lazy fetch annotation on your collections, if the context of your use case allow, the best way is for sure load one collection at time, using multiple queries. Here are some links that helped me when I faced this situation, here, and here
Answered By - Kaneda
Answer Checked By - Mildred Charles (JavaFixing Admin)