Конфигурация Spring выполняется в коде с использованием аннотаций вместо XML файла. Я пытался запросить некоторые данные и создать новые столбцы в базе данных ORACLE через спящий режим. Моя проблема в том, что hibernate генерирует только запросы SELECT, когда я использую sessionFactory.getCurrentSession(). Save(), hibernate не генерирует запросы INSERT. Я думаю, что это может быть проблема с транзакцией, но не может найти, где пошло не так. Я поставлю код ниже, и любая помощь будет оценена по достоинству.
Что основной класс конфигурации:
@Configuration
@ComponentScan
@EnableAutoConfiguration
@EnableTransactionManagement
@PropertySource({ "file:src/main/resources/Config/database.properties" })
public class QCWordImportExportTool {
@Autowired
private Environment env;
@Autowired
private WietHibernateInterceptor wietHibernateInterceptor;
/**
* main, says it all! :)
*
* @param args
*/
public static void main(String[] args) {
SpringApplication.run(QCWordImportExportTool.class, args);
}
@Bean
MultipartConfigElement multipartConfigElement() {
MultiPartConfigFactory factory = new MultiPartConfigFactory();
factory.setMaxFileSize("10MB");
factory.setMaxRequestSize("1024KB");
return factory.createMultipartConfig();
}
@Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(restDataSource());
sessionFactory.setPackagesToScan(new String[] { "com.ciena.prism.almtools.wiet" });
sessionFactory.setHibernateProperties(hibernateProperties());
sessionFactory.setEntityInterceptor(this.wietHibernateInterceptor);
return sessionFactory;
}
@Bean
public DataSource restDataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
dataSource.setUrl(env.getProperty("jdbc.url"));
dataSource.setUsername(env.getProperty("jdbc.username"));
dataSource.setPassword(env.getProperty("jdbc.password"));
return dataSource;
}
@Bean
public HibernateTransactionManager transactionManager() {
HibernateTransactionManager transactionManager = new HibernateTransactionManager();
transactionManager.setSessionFactory(sessionFactory().getObject());
return transactionManager;
}
@Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}
Properties hibernateProperties() {
return new Properties() {
private static final long serialVersionUID = 1L;
{
setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
setProperty("hibernate.globally_quoted_identifiers",
env.getProperty("hibernate.globally_quoted_identifiers"));
setProperty("hibernate.show_sql", env.getProperty("hibernate.show_sql"));
setProperty("hibernate.format_sql", env.getProperty("hibernate.format_sql"));
}
};
}
}
Класс Service - это интерфейс, и я отправлю класс Service Impl основным методом:
@Service
@Transactional(readOnly = true)
public class ImportExportManagerImpl implements ImportExportManager {
private TestFacade testFacade;
private TestFolderFacade testFolderFacade;
private UserManager userManager;
@Autowired
SessionFactory sessionFactory;
@Autowired
RequirementCoverageDAO requirementCoverageDao;
@Autowired
RequirementDAO requirementDao;
@Autowired
WietHibernateInterceptor wietHibernateInterceptor;
@Autowired
public ImportExportManagerImpl(TestFacade testFacade, TestFolderFacade testFolderFacade,
UserManager userManager) {
this.testFacade = testFacade;
this.testFolderFacade = testFolderFacade;
this.userManager = userManager;
}
/*
* (non-Javadoc)
*
* @see com.ciena.prism.almtools.wiet.managers.ImportExportManager#importTestCases(java.lang.String,
* java.lang.String, java.util.List)
*/
@Override
@Transactional(readOnly = false)
public void importTestCases(String domain, String project, List<TestCase> testCases)
throws RequestFailureException, RESTAPIException, InvalidDataException {
System.out.println("Start to import...");
setDBSchema(domain, project);
for (TestCase testCase : testCases) {
TestFolder testFolder = retrieveTestFolderFromPath(domain, project, testCase.getFolderPath());
Test test = new Test(testCase, testFolder);
ALMEntity almEntity = new ALMEntity(test);
Test existingTest = getExistingTest(domain, project, test);
if (existingTest == null) {
existingTest = new Test(testFacade.createEntity(domain, project, almEntity));
} else {
testFacade.updateEntity(domain, project, existingTest.getId(), almEntity);
}
System.out.println(existingTest.getName());
/* Create Requirement_Coverage using test and doors_object_ids */
List<String> doors_object_ids = testCase.getDoors_object_ids();
for (String doors_object_id : doors_object_ids) {
List<Requirement> requirementList = requirementDao.findAllFromDoorsobjectid(doors_object_id);
if (requirementList != null && !requirementList.isEmpty()) {
System.out.println("*************Requirement:" + doors_object_id + " not null");
/* check if the coverage already exist */
Requirement requirement = requirementList.get(0);
List<RequirementCoverage> requirementCoverageList = requirementCoverageDao
.findAllFromTestIdReqId(Integer.parseInt(existingTest.getId()),
requirement.getReqId());
if (requirementCoverageList == null || requirementCoverageList.isEmpty()) {
System.out.println("**************Creating new requirement coverage");
/* create a new Requirement Coverage Object */
RequirementCoverage requirementCoverage = new RequirementCoverage();
requirementCoverage.setRequirement(requirement);
requirementCoverage.setEntityId(Integer.parseInt(existingTest.getId()));
requirementCoverage.setEntityType("TEST");
requirementCoverageDao.create(requirementCoverage);
System.out.println("*********assigned DB id: " + requirementCoverage.getId());
}
} else {
throw new InvalidDataException("Requirement Management Tool Id : " + doors_object_id
+ " doesn't exist in QC");
}
}
}
}
}
И здесь класс DAO impl:
@Repository
public class RequirementCoverageDAOImpl implements RequirementCoverageDAO {
@Autowired
private SessionFactory sessionFactory;
@Override
public Integer create(RequirementCoverage requirementCoverage) {
return (Integer) sessionFactory.getCurrentSession().save(requirementCoverage);
}
}
Тогда класс сущностей:
@Entity
@Table(schema = "wiet", name = "REQ_COVER")
public class RequirementCoverage {
@SuppressWarnings("unused")
private static final long serialVersionUID = 1L;
@Id
@SequenceGenerator(name = "req_cover_id_gen", sequenceName = "wiet.REQ_COVER_SEQ", allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "req_cover_id_gen")
@Column(name = "RC_ITEM_ID", unique = true, nullable = false)
private Integer id;
@OneToOne
@JoinColumn(name = "RC_REQ_ID", nullable = false)
private Requirement requirement;
@Column(name = "RC_ENTITY_ID", nullable = false)
private Integer entityId;
@Column(name = "RC_ENTITY_TYPE", nullable = false)
private String entityType;
....setters and gettters...
}
Надеюсь, я прояснил это и поблагодарил за чтение.
WietHibernateInterceptor используется для динамического изменения схемы:
@Component
public class WietHibernateInterceptor extends EmptyInterceptor {
private static final long serialVersionUID = 1L;
private String schema;
@Override
public String onPrepareStatement(String sql) {
String prepedStatement = super.onPrepareStatement(sql);
if (prepedStatement.toLowerCase().contains("wiet.".toLowerCase())) {
/* As @SequenceGenerator ignores schema, sequence squery is manually set to be correct */
prepedStatement = prepedStatement.replaceAll("'", "\"");
prepedStatement = prepedStatement.replaceAll("wiet.", this.schema + "\".\"");
}
/* Change schema dynamically */
prepedStatement = prepedStatement.replaceAll("wiet", this.schema);
return prepedStatement;
}
public String getSchema() {
return schema;
}
public void setSchema(String schema) {
this.schema = schema;
}
}
Hibernate будет генерировать только инструкции INSERT, когда он очищает сеанс. Он очистит сеанс в следующих сценариях
@Transactional
заканчивается, Мои единственные идеи заключаются в том, что создается исключение, которое не попадает (но я бы ожидал, что он будет отображаться в ваших журналах или вашей консоли), что приводит к @Transactional
транзакции или что по какой-то причине сеанс @Transactional
не создается или не поддерживается.
Первое, что я попробую, удалить диалоги Hibernate из ваших свойств спящего режима. Hibernate делает фантастическую работу, определяющую, какой диалект использовать на основе драйвера, который вы ему даете, и (особенно с драйверами Oracle), если вы заставите его использовать другой диалект, он может вызвать странные ошибки.
2-я вещь, которую я постараюсь, - определить, есть ли SQLException, сгенерированное Hibernate. Я бы предположил, что вы уже включили ведение журнала спящего режима с помощью Log4J или любого используемого вами поставщика ведения журнала. Посмотрите, можете ли вы найти выброшенное SQLException
.
В аннотации @Transaction указано readOnly = true. Это означает, что в этой транзакции допускается только чтение. Удалить readOnly = true. Также посмотрите на управление весной транзакции 9.5.6. Использование @Transactional.