无法延迟初始化角色集合:myapp.myapp.models.Contact.messages,无法初始化代理 - 没有会话
Posted
技术标签:
【中文标题】无法延迟初始化角色集合:myapp.myapp.models.Contact.messages,无法初始化代理 - 没有会话【英文标题】:failed to lazily initialize a collection of role: myapp.myapp.models.Contact.messages, could not initialize proxy - no Session 【发布时间】:2019-05-26 14:44:29 【问题描述】:我遇到 org.hibernate.LazyInitializationException:。我已经研究了这些类似的问题Hibernate: LazyInitializationException: failed to lazily initialize a collection of role. Could not initialize proxy - no Session 和How to solve the “failed to lazily initialize a collection of role” Hibernate exception,但它们都没有帮助我的情况。我有 spring 自动配置我的数据源到我没有这个问题的地方,但是我添加了另一个数据源连接,然后为每个数据源创建了一个配置文件,现在一切正常,就像以前一样,但我一直收到这个错误抛出。我不知道该怎么办。任何帮助表示赞赏。
在我添加其他数据库之前,我的属性文件中的数据库信息如下所示
##############DBs##################
spring.jpa.database-platform=org.hibernate.dialect.mysql5InnoDBDialect
spring.jpa.hibernate.ddl-auto=update
spring.jpa.database=default
#Myapp DB
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/myapp? verifyServerCertificate=false&useSSL=false&requireSSL=false
spring.datasource.username=myusername
spring.datasource.password=mypassword
一切正常。
现在一切都是这样设置的。
属性文件
##############DBs##################
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.hibernate.ddl-auto=update
spring.jpa.database=default
#Myapp DB
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/myapp? verifyServerCertificate=false&useSSL=false&requireSSL=false
spring.datasource.username=myusername
spring.datasource.password=mypassword
#Other DB
spring.seconddatasource.driverClassName = com.mysql.jdbc.Driver
spring.seconddatasource.url = jdbc:mysql://localhost:3306/other
spring.seconddatasource.username=myusername
spring.seconddatasource.password=mypassword
###################################
联系实体:
@Entity
@Table(name = "contact")
public class Contact
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "contact")
private List<Messages> messages;
public long getId()
return this.id;
public void setId(long id)
this.id = id;
public List<Messages> getMessages()
return this.messages == null ? null : new ArrayList<>(this.messages);
public void setMessages(List<Messages> messages)
this.messages = messages;
public void addMessage(Messages message)
this.messages.add(message); // this is where the error is being thrown
消息实体:
@Entity
@Table(name = "message")
public class Contact
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@ManyToOne
@JoinColumn(name = "contactId", nullable = false)
private Contact contact;
public long getId()
return this.id;
public void setId(long id)
this.id = id;
public Contact getContact()
return this.contact;
public void setContact(Contact contact)
this.contact = contact;
New MyAppConfigClass(一旦与其他一起放入,错误就开始发生):
@ComponentScan
@Configuration
@EnableJpaRepositories(
basePackages = "myapp.myapp" ,
entityManagerFactoryRef = "myappEntityManagerFactory",
transactionManagerRef = "myappTransactionManager")
@EnableTransactionManagement
public class MyAppDBConfiguration
@Autowired private ApplicationContext applicationContext;
@Bean(name = "myappExceptionTranslator")
public HibernateExceptionTranslator personnelHibernateExceptionTranslator()
return new HibernateExceptionTranslator();
@Bean(name = "myappTransactionManager")
public PlatformTransactionManager personnelTransactionManager()
return new JpaTransactionManager(personnelEntityManagerFactory().getObject());
@Bean(name = "myappEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean personnelEntityManagerFactory()
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setGenerateDdl(true);
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(vendorAdapter);
factory.setPackagesToScan("myapp.myapp");
factory.setDataSource(myappDataSource());
factory.afterPropertiesSet();
return factory;
@Primary
@Bean(name = "myappDataConfig")
@ConfigurationProperties("spring.datasource")
public DataSourceProperties myappProperties()
return new DataSourceProperties();
@Bean(name = "myappData", destroyMethod = "")
public DataSource myappDataSource()
DataSourceProperties properties = myappProperties();
if (null != properties.getJndiName())
JndiDataSourceLookup lookup = new JndiDataSourceLookup();
DataSource source = lookup.getDataSource(properties.getJndiName());
excludeMBeanIfNecessary(source, "myappData");
return source;
else
return properties.initializeDataSourceBuilder().build();
private void excludeMBeanIfNecessary(Object candidate, String beanName)
try
MBeanExporter mbeanExporter = this.applicationContext.getBean(MBeanExporter.class);
if (JmxUtils.isMBean(candidate.getClass()))
mbeanExporter.addExcludedBean(beanName);
catch (NoSuchBeanDefinitionException ex)
// No exporter. Exclusion is unnecessary
这是OtherConfigClass(几乎完全一样):
@ComponentScan
@Configuration
@EnableJpaRepositories(
basePackages = "myapp.other" ,
entityManagerFactoryRef = "otherEntityManagerFactory",
transactionManagerRef = "otherTransactionManager")
@EnableTransactionManagement
public class OtherDBConfiguration
@Autowired private ApplicationContext applicationContext;
@Bean(name = "otherExceptionTranslator")
public HibernateExceptionTranslator personnelHibernateExceptionTranslator()
return new HibernateExceptionTranslator();
@Bean(name = "otherTransactionManager")
public PlatformTransactionManager personnelTransactionManager()
return new JpaTransactionManager(personnelEntityManagerFactory().getObject());
@Bean(name = "otherEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean personnelEntityManagerFactory()
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setGenerateDdl(true);
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(vendorAdapter);
factory.setPackagesToScan("myapp.other");
factory.setDataSource(otherDataSource());
factory.afterPropertiesSet();
return factory;
@Bean(name = "otherDataConfig")
@ConfigurationProperties("spring.seconddatasource")
public DataSourceProperties otherProperties()
return new DataSourceProperties();
@Bean(name = "otherData", destroyMethod = "")
public DataSource textappotherDataSource()
DataSourceProperties properties = myappProperties();
if (null != properties.getJndiName())
JndiDataSourceLookup lookup = new JndiDataSourceLookup();
DataSource source = lookup.getDataSource(properties.getJndiName());
excludeMBeanIfNecessary(source, "otherData");
return source;
else
return properties.initializeDataSourceBuilder().build();
private void excludeMBeanIfNecessary(Object candidate, String beanName)
try
MBeanExporter mbeanExporter = this.applicationContext.getBean(MBeanExporter.class);
if (JmxUtils.isMBean(candidate.getClass()))
mbeanExporter.addExcludedBean(beanName);
catch (NoSuchBeanDefinitionException ex)
// No exporter. Exclusion is unnecessary
这是应用程序类:
@EnableAutoConfiguration
@SpringBootApplication
public class MyApplication
public static void main(String[] args)
SpringApplication.run(MyApplication.class, args);
所以我假设我在 AutoConfig 之外完成的新配置文件中遗漏了一些东西。这是我做的唯一改变,它开始抛出错误。就像我上面说的,数据已正确保存到数据库中,但仍然会抛出该错误。
我不知道为什么会这样,解释一下会很有帮助。
更新:
ContactRepository:
@Repository
public interface ContactRepository extends JpaRepository<Contact, Long>
MessagesRepository:
@Repository
public interface MessagesRepository extends JpaRepository<Messages, Long>
服务类:
@Service
public void serviceClass(long id)
Contact contact = contactRepository.findOne(id);
Messages msg = new Messages();
msg.setContact(contact);
// do some work here
Messages savedMessage = messagesRepository.save(msg);
contact.addMessage(savedMessage);
contactRepository.save(contact);
【问题讨论】:
您在 JPA 实体上缺少默认的无参数构造函数,所以我认为这是一个错字。您还可以分享您正在做什么来检索实体吗? – 通常在“服务”类 +“存储库”上。 @x80486 我的存储库只是扩展的 JpaRepositories。我发布了存储库和服务类。如果您需要更多信息,请告诉我。 好的,我回答的内容仍然是最新的。您有服务级别的@Transactional
吗?
【参考方案1】:
在 application.properties 文件中设置 enable_lazy_load_no_trans=true 解决了我的情况,而无需将提取类型从惰性更改为渴望。
【讨论】:
小修正:应该是spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true【参考方案2】:您只能在事务上下文中进行延迟加载。 在您的服务类上使用 @Transactional 注释:
@Service
@Transactional
public class Service
public void serviceClass(long id)
Contact contact = contactRepository.findOne(id);
Messages msg = new Messages();
msg.setContact(contact);
// do some work here
Messages savedMessage = messagesRepository.save(msg);
contact.addMessage(savedMessage);
contactRepository.save(contact);
【讨论】:
【参考方案3】:如果您在 application.properties 配置文件中添加以下行,那么它应该可以工作
spring.jpa.open-in-view=false
【讨论】:
【参考方案4】:有几种方法可以在 Hibernate 中初始化惰性关联,但归根结底,您应该能够通过 (1) 使用 FETCH JOIN
(如果使用 Criteria API 或自定义、原生或非原生查询),或 (2) 使用命名/动态实体图。
在Contact
中尝试这样的事情:
@Entity
@Table(name = "contact")
@NamedEntityGraph(name = "graph.Contact.messages",
attributeNodes = @NamedAttributeNode("messages"))
public class Contact ...
如果您有访问权(和时间)使用EntityManager
,所有这一切都很简单。我记得 Spring Data JPA 在实体图方面遇到了一些问题,但我认为你的情况应该是开箱即用的。
您也可以尝试FETCH JOIN
,例如:SELECT c FROM Contact AS c JOIN FETCH c.messages m WHERE c.id = :id"
- 可能需要对其进行调整,我只是“即时”编写的。
注意:此外,由于您使用的是 Spring,请确保您的“服务”类使用 @Transactional
注释,因为延迟加载仅在(相同)事务上下文中有效.
请不要将您的
FetchType.LAZY
变成FetchType.EAGER
- 除非您将失去工作;)同时,在映射关系上调用方法是一种 hack,会带你到所谓的
N + 1
问题。
【讨论】:
以上是关于无法延迟初始化角色集合:myapp.myapp.models.Contact.messages,无法初始化代理 - 没有会话的主要内容,如果未能解决你的问题,请参考以下文章
org.hibernate.LazyInitializationException:无法延迟初始化角色集合:FQPropretyName,无法初始化代理 - 无会话
LazyInitializationException: 延迟初始化角色集合失败 无法初始化代理 - 没有会话
无法延迟初始化角色集合:myapp.myapp.models.Contact.messages,无法初始化代理 - 没有会话
未能延迟初始化角色集合:无法初始化代理 - Hibernate 中的 @ManyToMany 映射注释中没有会话错误? [复制]