#hibernate #jax-rs
#спящий режим #jax-rs
Вопрос:
Я пытаюсь получить идентификатор объекта после вызова persist() менеджера объектов. Однако после вызова persist() Я не получаю идентификатор. Также em.refresh() завершается с ошибкой. Я использую многопользовательскую базу данных Hibernate. Все работало нормально до того, как я ввел многопользовательскую среду.
Это то, что у меня есть:
public class MyEntity{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "ID")
.....
}
@Stateless
public class ActionDAO{
......
@PersistenceContext(unitName = "project-persistence-unit")
protected EntityManager em;
public void saveEntity(MyEntity q) {
if (q.getId() == null) {
em.persist(q);
System.out.println(q.getID); // expect to get an ID here but i get 0 .
} else {
em.merge(q);
}
}
}
Я искал, но не смог найти решение!
Классы с несколькими арендаторами приведены ниже:
public class CurrentTenantIdentifierResolverImpl implements CurrentTenantIdentifierResolver {
@Override
public String resolveCurrentTenantIdentifier() {
String tenant = ThreadState.INSTANCE.getTenantId();
return tenant;
}
@Override
public boolean validateExistingCurrentSessions() {
return true;
}
}
public class MultiTenantConnectionProviderImpl extends AbstractMultiTenantConnectionProvider {
@Override
protected ConnectionProvider getAnyConnectionProvider() {
Properties properties = new Properties();
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setUrl("jdbc:mysql://localhost:8889/project1?serverTimezone=UTC");
ds.setUsername("root");
ds.setPassword("root");
DatasourceConnectionProviderImpl d = new DatasourceConnectionProviderImpl();
d.setDataSource(ds);
d.configure(properties);
return (ConnectionProvider) d;
}
@Override
protected ConnectionProvider selectConnectionProvider(String tenantId) {
Properties properties = new Properties();
String path = MyConstants.DOCUMENT_ROOT "/" tenantId.toUpperCase();
File file = new File(path File.separator "DATABASE.properties");
if (file.exists()) {
Properties prop = new Properties();
try {
InputStream input = new FileInputStream(path "/DATABASE.properties");
prop.load(input);
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setUrl(prop.getProperty("URL"));
ds.setUsername(prop.getProperty("USERNAME"));
ds.setPassword(prop.getProperty("PASSWORD"));
input.close();
DatasourceConnectionProviderImpl d = new DatasourceConnectionProviderImpl();
d.setDataSource(ds);
d.configure(properties);
return (ConnectionProvider) d;
} catch (IOException | NullPointerException ex) {
Logger.getLogger(MultiTenantConnectionProviderImpl.class.getName()).log(Level.SEVERE, null, ex);
ex.printStackTrace();
}
}
return null;
}
}
Persistence.xml
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="project-persistence-unit" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<!--<jta-data-source>java:/PROJECT-DS</jta-data-source>-->
<properties>
<property name="hibernate.jdbc.time_zone" value="UTC"/>
<property name="hibernate.archive.autodetection" value="class"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/>
<property name="hibernate.jdbc.batch_size" value="250"/>
<property name="hibernate.jdbc.fetch_size" value="500"/>
<property name="hibernate.order_inserts" value="true"/>
<property name="hibernate.order_updates" value="true"/>
<property name="jboss.entity.manager.jndi.name" value="java:/myprojectEM"/>
<property name="jboss.entity.manager.factory.jndi.name" value="java:/myprojectEMF"/>
<property name="hibernate.generate_statistics" value="false"/>
<property name="hibernate.multi_tenant_connection_provider" value="com.myproject.auxiliary.MultiTenantConnectionProviderImpl"/>
<property name="hibernate.tenant_identifier_resolver" value="com.myproject.auxiliary.CurrentTenantIdentifierResolverImpl"/>
<property name="hibernate.multiTenancy" value="DATABASE"/>
<property name="hibernate.enable_lazy_load_no_trans" value="true"/>
</properties>
</persistence-unit>
</persistence>
Комментарии:
1. Попробуйте добавить аннотацию @Transactional поверх вашего метода saveEntity или начните транзакцию с помощью em.getTransaction().begin() перед сохранением объекта, а затем зафиксируйте транзакцию с помощью em.getTransaction().commit()
2. Спасибо Onur. Добавление @Transactional правильно выдает ошибку («Транзакция недоступна при использовании JTA с включенным доступом к транзакциям, совместимым с JPA»), потому что я использую JTA в качестве своего типа транзакции. Обратите внимание, что когда я удаляю многопользовательскую среду, я могу получить идентификатор. Я, должно быть, что-то упускаю?
3. Я вижу! Хорошо, извините. На самом деле может быть много возможностей. Прежде всего, постарайтесь убедиться, что транзакция зафиксирована. Может быть, проблема с сеансом или состоянием объекта! Может быть, currentTenantIdentifier не может быть разрешен правильно? Просто проверьте это baeldung.com/hibernate-5-multitenancy и просмотрите свою конфигурацию после того, как убедитесь, что транзакция зафиксирована!
4. Спасибо Onur. Я решил это, изменив источник данных с ‘DriverManagerDataSource’ на ‘BasicDataSource’ (в моем MultiTenantConnectionProviderImpl).
Ответ №1:
Обновите класс MultiTenantConnectionProviderImpl, чтобы использовать org.apache.commons.dbcp.BasicDataSource вместо org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl