Spring Hibernate: Entity seems not persisted, no failures either - java

My model is
import javax.annotation.Nonnull;
import javax.persistence.Entity;
import org.joda.time.DateTime;
#Entity
public class Network extends AbstractEntity {
private long networkId;
private String name;
private boolean active;
private DateTime createdAt;
private String createdBy;
private DateTime updatedAt;
private String updatedBy;
...
}
AbstractEntity is
#MappedSuperclass
public class AbstractEntity {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
public Long getId() {
return id;
}
#Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
final AbstractEntity abstractEntity = (AbstractEntity) obj;
return id.equals(abstractEntity.id);
}
#Override
public int hashCode() {
return id == null ? 0 : id.hashCode();
}
}
I have Repository where I want to add entity. I do
#Repository
public class NetworkRepositoryImpl implements NetworkRepository {
#PersistenceContext
private EntityManager entityManager;
#Override
#Nonnull
public List<Network> findAll() {
//noinspection JpaQlInspection
final Query query = entityManager.createQuery("SELECT e FROM Network e");
return (List<Network>)query.getResultList();
}
#Nonnull
#Override
#Transactional
public Network save(#Nonnull final Network network) {
if (network.getId() == null) {
entityManager.persist(network);
return network;
} else {
return entityManager.merge(network);
}
}
}
and I Test it as
#Test
public void testAllNetworks() {
final Network network = new Network(1, "US", true, DateTime.now());
final Network networkInDb = networkRepository.save(network);
assertNotNull(networkInDb.getId());
final List<Network> networks = networkRepository.findAll();
assertTrue(networks.isEmpty());
}
my ApplicationConfig looks like
#Configuration
#ComponentScan
#EnableJpaRepositories
public class ApplicationConfig {
#Bean
public DataSource dataSource() {
final EmbeddedDatabaseBuilder embeddedDatabaseBuilder = new EmbeddedDatabaseBuilder();
embeddedDatabaseBuilder.setType(EmbeddedDatabaseType.H2);
return embeddedDatabaseBuilder.build();
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
final HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
jpaVendorAdapter.setDatabase(Database.H2);
jpaVendorAdapter.setGenerateDdl(true);
final LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
localContainerEntityManagerFactoryBean.setJpaVendorAdapter(jpaVendorAdapter);
localContainerEntityManagerFactoryBean.setPackagesToScan("com.org.comma.persistence");
localContainerEntityManagerFactoryBean.setDataSource(dataSource());
localContainerEntityManagerFactoryBean.setPersistenceUnitName("test-comma-pu");
return localContainerEntityManagerFactoryBean;
}
#Bean
public PlatformTransactionManager transactionManager() {
final JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
return transactionManager;
}
}
My test fails on line
assertNotNull(networkInDb.getId());
meaning the entity is not persisted
What I am doing wrong here?

In my case, I was using wrong annotation.
I was using
import javax.transaction.Transactional;
instead, what I needed was
import org.springframework.transaction.annotation.Transactional;
Atleast I see it try persisting and failing somewhere else

If your test fails because Id value is null, then it is expected behavior.
When hibernate persist an entity, it will not fetch the auto-generated key value automatically. You should either find the entity again or refresh it manually.
In similar situation, I usually refresh the entity like below.
entityManager.persist(network);
entityManager.flush();
entityManager.refresh(network);
P.S: You should flush before refreshing to make it reliable.

Related

Export from Oracle and Import to Azure SQL reusing Entities Spring Boot

I'm trying to fetch data from an Oracle DB and import it to Azure Sql. The databases have the same structure and therefore I was thinking if I could use the same entities and repositories with different datasources for it.
#Entity
#Table(name = "Street", indexes = {#Index(name = "street_id_index", columnList = "streetid")})
public class Street {
#Id
private String streetid;
public String streetcode;
public String streetname;
public String streetnameaddd;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "municipalitycode", referencedColumnName = "municipalitycode")
public Municipality municipalitycode;
public String is_deleted;
}
public interface Street_Repository extends JpaRepository<Street,String> {
List<Street> findAll();
}
#Configuration
public class AzureConfig {
#Bean("AzureDataSource")
#ConfigurationProperties(prefix = "spring.datasource-azure-sql")
public DataSource dataSourceAzureSql(){
return DataSourceBuilder.create().build();
}
}
#Configuration
public class OracleConfig {
#Bean
#ConfigurationProperties(prefix = "spring.datasource-oracle")
public DataSource dataSourceOracle(){
return DataSourceBuilder.create().build();
}
}
spring:
datasource-azure-sql:
jdbc-url: jdbc:sqlserver://xxxxxxx.database.windows.net:1433;database=xxxxxxxxxxx-xxx;user=xxxxx#xxxxx;password=xxxxxxxxx;encrypt=true;trustServerCertificate=false;hostNameInCertificate=xxxxxxxx;loginTimeout=30
datasource-oracle:
jdbc-url: jdbc:oracle:thin:#xxxxx.xx.xxx:xxx:ssid
#Repository
public class Stree_Repo implements Street_Repository {
private JdbcTemplate jdbcTemplate;
#Autowired
#Qualifier("AzureDataSource")
public void setDataSource(DataSource dataSource){
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
#Autowired
#Qualifier("OracleDataSource")
public void setDataSource2(DataSource dataSource){
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
#Override
public List<Street> findAll() {
return null;
}
... rest override methods...
}
So the classe Street_Repo implements the interface and because this Entity is part of both Oracle and Azure I was wondering if there was a possible of not repeating the Entity and all the other classes associated.
Thank you in advance!

Is there a way to map mutliple databases with same table names in a dynamic way?

First time I encounter this problem. The situation is:
I have more than 100 SQL databases, each one correspond to a different company and each one have the same three tables (same table names, same column names, same column data type).
Is there some way to map all these databases dynamically?
With dynamically I mean to have one class to which I can refer and make any CRUD operation.
After some research I could see what I wanted to do:
Basically I needed to change my data source in run time, for that I used a spring framework interface called AbstracRoutingDataSource.
Example:
Implementing AbstractRoutingDataSource:
public class MultiRoutingDataSource extends AbstractRoutingDataSource {
#Override
protected Object determineCurrentLookupKey() {
return DBContextHolder.getCurrentDb();
}
}
DatabaseContextHolder:
public class DBContextHolder {
private static final ThreadLocal<DBTypeEnum> contextHolder = new ThreadLocal<>();
public static void setCurrentDb(DBTypeEnum dbType) {
contextHolder.set(dbType);
}
public static DBTypeEnum getCurrentDb() {
return contextHolder.get();
}
public static void clear() {
contextHolder.remove();
}
}
Database type enum:
public enum DBTypeEnum{
DATASOURCE1("DATASOURCE1"),
DATASOURCE2("DATASOURCE2");
DBTypeEnum(final String dbTypeEnum){
this.dbTypeEnum = dbTypeEnum;
}
private String dbTypeEnum;
public String dbTypeEnum(){
return dbTypeEnum;
}
}
Persistence configuration:
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(
basePackages = "base.packages.path",
entityManagerFactoryRef = "multiEntityManager",
transactionManagerRef = "multiTransactionManager"
)
public class PersistenceConfiguration {
private final String PACKAGE_SCAN = "base.package.path";
#Bean(name = "dataSource1")
#ConfigurationProperties("spring.datasource1")
public DataSource dataSource1() {
return DataSourceBuilder.create().build();
}
#Bean(name = "dataSource2")
#ConfigurationProperties("spring.datasource2")
public DataSource dataSource2() {
return DataSourceBuilder.create().build();
}
#Bean(name = "multiRoutingDataSource")
public DataSource multiRoutingDataSource() {
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put(DBTypeEnum.DATASOURCE1, dataSource1());
targetDataSources.put(DBTypeEnum.DATASOURCE2, dataSource2());
MultiRoutingDataSource multiRoutingDataSource = new MultiRoutingDataSource();
multiRoutingDataSource.setDefaultTargetDataSource(dataSource1());
multiRoutingDataSource.setTargetDataSources(targetDataSources);
return multiRoutingDataSource;
}
#Bean(name = "multiEntityManager")
public LocalContainerEntityManagerFactoryBean multiEntityManager() {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(multiRoutingDataSource());
em.setPackagesToScan(PACKAGE_SCAN);
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaProperties(hibernateProperties());
return em;
}
#Bean(name = "multiTransactionManager")
public PlatformTransactionManager multiTransactionManager() {
JpaTransactionManager transactionManager
= new JpaTransactionManager();
transactionManager.setEntityManagerFactory(
multiEntityManager().getObject());
return transactionManager;
}
#Bean(name = "dbSessionFactory")
public LocalSessionFactoryBean dbSessionFactory() {
LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean();
sessionFactoryBean.setDataSource(multiRoutingDataSource());
sessionFactoryBean.setPackagesToScan(PACKAGE_SCAN);
sessionFactoryBean.setHibernateProperties(hibernateProperties());
return sessionFactoryBean;
}
private Properties hibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.show_sql", true);
properties.put("hibernate.format_sql", true);
return properties;
}
}
Then you need to have all of your database information in a .properties file:
spring.datasource1.jdbcUrl=jdbc:sql:sql-url:3306/datasource1
spring.datasource1.username=username
spring.datasource1.password=password
spring.datasource1.driver-class-name= Driver
spring.datasource2.jdbcUrl=jdbc:sql:sql-url:3306/datasource2
spring.datasource2.username=username
spring.datasource2.password=password
spring.datasource2.driver-class-name= Driver
Then you need to map your entity:
#Entity
#Table(name = "table_name")
#Getter
#Setter
public class MyEntity implements Serializable {
#Id
#Column(name = "ID", columnDefinition = "varchar(17)")
private String id;
//more fields...
}
I used spring CrudRepositories interface for this entity
public interface IMyEntityRepository extends CrudRepository<MyEntity, String> {
}
Finally my controller is prepared to change datasource depending on a JSON field in my request.
JSON:
{
"dataSource":"DATASOURCE1"
//more fields ...
}
RESTController:
#PutMapping("/url/{id}")
public ResponseEntity<?> editMyEntity(#RequestBody RequestObject request #PathVariable String id){
DBContextHolder.setCurrentDb(DBTypeEnum.valueOf(request.getDataSource);
iMyEntitiRepository.getMyEntity(id);
//...
}

Spring-Data: Unknown entity with Java configuration

My project structure looks like
persistence/pom.xml
src/main/java/
ApplicationConfig
NetworkRepository
NetworkRepositoryImpl
Network
src/main/test/NetworkRepositoryTest
My ApplicationConfig looks like
#Configuration
#ComponentScan
#EnableJpaRepositories
public class ApplicationConfig {
#Bean
public DataSource dataSource() {
final EmbeddedDatabaseBuilder embeddedDatabaseBuilder = new EmbeddedDatabaseBuilder();
embeddedDatabaseBuilder.setType(EmbeddedDatabaseType.H2);
return embeddedDatabaseBuilder.build();
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
final HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
jpaVendorAdapter.setDatabase(Database.H2);
jpaVendorAdapter.setGenerateDdl(true);
final LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
localContainerEntityManagerFactoryBean.setJpaVendorAdapter(jpaVendorAdapter);
localContainerEntityManagerFactoryBean.setPackagesToScan(getClass().getPackage().getName());
localContainerEntityManagerFactoryBean.setDataSource(dataSource());
localContainerEntityManagerFactoryBean.setPersistenceUnitName("test-comma-pu");
return localContainerEntityManagerFactoryBean;
}
#Bean
public PlatformTransactionManager transactionManager() {
final JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
return transactionManager;
}
}
my Network entity looks like
import javax.annotation.Nonnull;
import javax.persistence.Entity;
import org.joda.time.DateTime;
#Entity
public class Network extends AbstractEntity {
private final long networkId;
private final String name;
private final boolean active;
private final DateTime createdAt;
private String createdBy;
private DateTime updatedAt;
private String updatedBy;
...
}
My NetworkRepository looks like
import java.util.List;
import javax.annotation.Nonnull;
import org.springframework.data.repository.Repository;
import com.org.comma.persistence.entities.Network;
public interface NetworkRepository extends Repository<Network, Long> {
#Nonnull
List<Network> findAll();
#Nonnull
Network save(#Nonnull final Network network);
}
My NetworkRepositoryImpl looks like
#Repository
#Transactional
public class NetworkRepositoryImpl implements NetworkRepository {
#PersistenceContext
private EntityManager entityManager;
#Override
#Nonnull
public List<Network> findAll() {
return Collections.emptyList();
}
#Nonnull
#Override
public Network save(#Nonnull final Network network) {
if (network.getId() == null) {
entityManager.persist(network);
return network;
} else {
return entityManager.merge(network);
}
}
}
and my Test looks like
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = {ApplicationConfig.class, NetworkRepositoryImpl.class})
#Transactional
public class NetworkRepositoryTest {
#Autowired
NetworkRepository networkRepository;
#Test
public void testAllNetworks() {
Network network = new Network(1, "US", true, DateTime.now());
network = networkRepository.save(network);
final List<Network> networks = networkRepository.findAll();
assertTrue(networks.isEmpty());
}
}
When I run test, I see error as
java.lang.IllegalArgumentException: Unknown entity: com.org.comma.persistence.entities.Network
I found people recommending to have persistence.xml, My question is when I am already using Java Based Configuration(ApplicationConfig) and also set the base packages to scan
localContainerEntityManagerFactoryBean.setPackagesToScan(getClass().getPackage().getName());
even in that case I need persistence.xml?
The problem was
localContainerEntityManagerFactoryBean.setPackagesToScan(getClass().getPackage().getName());
getClass().getPackage().getName() resolved to com.org.comma.persistence.config but all the entities were in com.org.comma.persistence
Doing the following
localContainerEntityManagerFactoryBean.setPackagesToScan("com.yahoo.comma.persistence");
helped me fix the issue and get rid of persistence.xml

Lazy Loading of One to Many Doesnt Work

I have 2 entities - Media and Keyword with one to many relationship. I though I marked the fetch to Lazy Madia is still fetching all the keywords.
I am using spring 3.2 Hibernate 4.3.4
Media Entity:
#Entity
public class Media {
#Id
#NotNull
#Column(name = "mediaid")
private String mediaId;
#NotNull
#OneToMany(cascade = CascadeType.ALL, mappedBy = "media", fetch = FetchType.LAZY)
private List<Keyword> keywords;
public List<Keyword> getKeywords() {
return keywords;
}
public void setKeywords(List<Keyword> keywords) {
if ( this.keywords!=null && this.keywords.size()>0 )
this.keywords.addAll(keywords);
else
this.keywords = keywords;
for (Keyword keyword : keywords) {
keyword.setMedia(this);
}
}
}
Keyword Entity:
#Entity(name = "keywords")
public class Keyword {
#Id
#NotNull
#Column(unique = true)
private String idKey;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "idmedia")
private Media media;
public Media getMedia() {
return media;
}
public void setMedia(Media media) {
this.media = media;
if (idKey == null || idKey.isEmpty())
setIdKey(this.media.getMediaId());
else
setIdKey(this.media.getMediaId() + "_" + idKey);
if (!media.containsKeyword(this))
media.getKeywords().add(this);
}
}
I can see the entities being fetch in the show_sql output but also this test fails
#WebAppConfiguration
#ContextConfiguration(classes = {PersistenceConfig.class})
#Transactional
#TransactionConfiguration(defaultRollback = true)
public class MediasRepositoryTest extends AbstractTransactionalTestNGSpringContextTests {
#Autowired
MediasRepository mediasRepository;
#PersistenceContext
EntityManager manager;
public void thatMediaLazyLoadsKeywords() throws Exception {
PersistenceUnitUtil unitUtil = manager.getEntityManagerFactory().getPersistenceUnitUtil();
Media media = DomainFixtures.createMedia();
Media savedMedia = mediasRepository.save(media);
Media retrievedMedia = mediasRepository.findOne(savedMedia.getMediaId());
assertNotNull(retrievedMedia);
assertFalse(unitUtil.isLoaded(retrievedMedia, "keywords"));
}
}
Configuration:
#EnableTransactionManagement
public class PersistenceConfig {
static Logger logger = LoggerFactory.getLogger(PersistenceConfig.class);
#Autowired
private Environment env;
// #Value("${init-db:false}")
private String initDatabase = "false";
#Bean
public DataSource dataSource()
{
logger.info("Starting dataSource");
BasicDataSource dataSource = new BasicDataSource();
logger.info("jdbc.driverClassName"+ env.getProperty("jdbc.driverClassName"));
dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
dataSource.setUrl(env.getProperty("jdbc.url"));
dataSource.setUsername(env.getProperty("jdbc.username"));
dataSource.setPassword(env.getProperty("jdbc.password"));
logger.info("End dataSource");
return dataSource;
}
#Bean
public EntityManagerFactory entityManagerFactory() throws SQLException
{
logger.info("Starting entityManagerFactory");
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setGenerateDdl(Boolean.TRUE);
vendorAdapter.setShowSql(Boolean.parseBoolean(env.getProperty("hibernate.show_sql")));
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(vendorAdapter);
factory.setPackagesToScan("....");
factory.setDataSource(dataSource());
Properties jpaProperties = new Properties();
jpaProperties.put("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
jpaProperties.put("hibernate.enable_lazy_load_no_trans", true);
jpaProperties.put("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect");
factory.setJpaProperties(jpaProperties);
factory.afterPropertiesSet();
logger.info("End entityManagerFactory");
return factory.getObject();
}
.
.
.
}
You test is running in the context of a single transaction.
The Keywords are not being fetched, they're still in the persistence context from when you created them.
Try adding a manager.clear() after your save method call.
FetchType.LAZY is just a hint to the persistence provider, it is not a setting you can rely on. The persistence provider is free to load the attributes whenever it sees fit.
Thus you cannot reliably test whether lazy loading works as expected.

Spring+Hibernate Integration: Transaction Manager doesn't work using #Transactional

Spring configuration is done in code using annotations instead of XML file. I was trying to query some data and create new columns into ORACLE database through hibernate. My problem is that hibernate only generates SELECT queries, when I use sessionFactory.getCurrentSession().save(), hibernate doesn't generate INSERT queries. I think this could be a transaction issue but couldn't find where went wrong. I'll put code below and any help will be appreciated.
That's the main configuration class:
#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"));
}
};
}
}
The Service class is an interface and I'll post the Service Impl class with the main method:
#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");
}
}
}
}
}
And here's the DAO impl class:
#Repository
public class RequirementCoverageDAOImpl implements RequirementCoverageDAO {
#Autowired
private SessionFactory sessionFactory;
#Override
public Integer create(RequirementCoverage requirementCoverage) {
return (Integer) sessionFactory.getCurrentSession().save(requirementCoverage);
}
}
Then Entity Class:
#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...
}
Hope I have put this clear and thanks for reading.
WietHibernateInterceptor is used to change schema dynamically:
#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 will only generate the INSERT statements when it flushes the session. It will flush the session in the following scenarios
When the #Transactional method ends,
When it reaches its batch limit (if configured for batch inserts) or,
When you call a query that it detects needs the session to be
flushed eg you call a count() method. Hibernate would flush the
transactional session and commit it so that count() returns an
accurate value of records.
My only ideas is that an exception is being thrown that isn't being caught (but I would have expected it to show in your logs or your console) which is causing your transaction to roll back, or that for some reason the #Transactional session isn't being created or maintained or something.
1st thing I'd try, remove the Hibernate dialect from your hibernate properties. Hibernate does a fantastic job determining which dialect to use based on the driver you give it, and (especially with Oracle drivers) if you force it to use a different dialect it can produce strange errors.
2nd thing I'd try is to determine if there are any SQLException's being thrown by Hibernate. I'd assume that you have already turned on your hibernate logging using Log4J or whatever logging provider you are using. See if you can find an SQLException being thrown.
Your #Transaction annotation says readOnly = true. That means only read is allowed in that transaction. Remove readOnly = true.
Also look at the Spring Transaction management 9.5.6. Using #Transactional.

Categories

Resources