How to test Dao with Dbunit for table which is not having hibernate entity - spring

I have wrote a test class for Dao using DbUnit and dataset
Here is my class :
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "classpath:config/appContext-test.xml" })
#TestExecutionListeners({DependencyInjectionTestExecutionListener.class, DBUnitTestExecutionListener.class })
#DBUnitConfiguration(locations = { "testdata/mso_data.xml" })
public class TestMsoJobsDao{
#Resource
private MsoJobsDao msoJobsDao;
#Test
public void testSaveMsoDataIntoTempTable() throws Exception{
List<Object[]> msoHeadendList = new ArrayList<Object[]>();
Timestamp timestamp1 = Timestamp.valueOf("2015-07-01 08:49:50");
Object[] obj1 = {"TEST_MSO_SERVICE_ID_3","America/Detroit","SL","1",timestamp1,"1",timestamp1};
msoList.add(obj1);
msoJobsDao.saveMsoDataIntoTempTable(msoList);
}
}
and data set is :
<?xml version='1.0' encoding='UTF-8'?>
<dataset>
<mso_temp id="1" mso_service_id="TEST_MSO_SERVICE_ID_3"
timezone="America/Detroit" customer_group="RC" created_by="1"
created_date="2015-10-05 06:31:59" updated_by="1"
updated_date="2015-10-05 06:31:59"/>
</dataset>
When i am running my test case i am getting org.dbunit.dataset.NoSuchTableException: mso_temp
My problem is i don't need any entity as i am connecting to other database and saving the data from there to the temp table in our application database using PreparedStatement.If i create entity class the test case runs fine.
Is there any way through which DBUnit will consider the table for which entity class is not there.

dbUnit does not use entity classes, it directly uses JDBC. The dbUnit error is table does not exist, and dbUnit does not create tables. Your application / test setup creates the tables from the entity classes, so without the entity, the table does not exist.
For needed tables without entities, test setup must create these tables. For ease, you may want to just put the entity in the test classes folder. Another option is to run DDL that creates the table(s) before running all tests.

Related

Jpa Respository and its tests

This is more of a question regarding concept rather than an error I am facing.
So here I have two JPA respositories refereing to two tables in database
Teacher - has foreign key reference to departmentid
Depeartment - contains depeartment infos
Now to test the DepartmentRepositoryIntegrationTest I have to delete all the entries of teachers and then the depeartments. I understand I have a foreign key reference to departments so I cant delete any entry inside the department which is being consumed by the Teacher table. But When I was running this test there was nothing saved or inserted in the teachers table still I was getting DataIntergityViolationException. Why was there such enforcement to delete teachers table entries even though it was empty manually???
Couldnt find anything relevant to my doubt.
I am running the tests against the inmemory database like H2.
#SpringBootTest(webEnvironment = RANDOM_PORT)
#RunWith(SpringJUnit4ClassRunner.class)
#TestPropertySource(properties = {
"spring.datasource.url=jdbc:sqlserver://localhost:1433;loginTimeout=30;",
"spring.datasource.username="random",
"spring.datasource.password="random"
})
public class DepartmentRepositoryIntegrationTest {
#Autowired
private DepartmentRepository departmentRepository;
#Autowired
private FacultyRepository facultyRepository;
#Before
public void setUp() {
departmentRepository.deleteAll();
facultyRepository.deleteAll();
}

How to populate H2 DB UUID primary key using sql file in Spring Boot

I am developing a Spring Boot-2.4 application which use Spring Data JPA and I am writing test for my CURD implementation. I have few scenarios needs to load table data with specific primary key values before my test execution. I thought of using import.sql or data.sql in which i can write native SQL queries and use those supplied primary key values. As my primary key is defined as UUID eventhough I gave valid UUID data in SQL while fetching using findById its not working.
data.sql
insert into TEST_TABLE(id,name,pass) value ('2B12245566587878779679','test','xxxxx');
Assume given UUID value is valid and I can able to insert this data in H2 and able to view.
But when in JPA try to access this same ID using findById('2B12245566587878779679') will not returning this record. Is there any correct way to load the UUID and access it using .sql file.
EDIT: Included code sample
#Entity(name="TEST_TABLE")
public class TestTable{
#Id
#GeneratedValue
private UUID id;
}
#Repository
public interface TestTableRepository extends JpaRepository<TestTable,UUID>{}
#Service
public class TestTableService {
#Autowired
TestTableRepository testTableRepository;
public UUID getTableData(UUID id){
testTableRepository.findById(id); // here passing 2B12245566587878779679
}
}
Expecting one row returned but its not returning any

How to give dynamic value to #Table(name=p+"name") in spring JPA

name of the table should be fixed but in my scenario the last part of the table name is profile based so in local it is X but in dev it is Y and so on till Prod. Is there way to add dynamically the value to the table name.
The question tries to implement a bad practice. Don't do that.
Currently, Spring, Hibernate, and JPA does not support your configuration type.
You can use Hibernate interceptors to change the table in the generated SQL statements.
For your case you can define your table class like this:
#Entity
#org.hibernate.annotations.Proxy(lazy=false)
#Table(name=TableNameReplacer.PLACEHOLDER, schema="MySchema")
#Inheritance(strategy=InheritanceType.SINGLE_TABLE)
public class ProfileData implements Serializable {
and define your Hibernate interceptor in a following way:
public class TableNameReplacer extends EmptyInterceptor {
public static final String TABLE_PLACEHOLDER = "{table_placeholder}";
#Override
public String onPrepareStatement(String sql) {
if (sql.contains(TABLE_PLACEHOLDER )) {
String replacement = "{your logic to fill proper table name}";
sql = sql.replace(TABLE_SUFFIX_PLACEHOLDER, replacement);
}
return super.onPrepareStatement(sql);
}
Using this approach you're free to modify generated SQL and replace the table name there as you wish.
I recommend to use good placeholder value which you're sure will not be a part of actual values being saved to the table (or you can only limit this to select statements if you only read the data).

H2 JdbcSQLException: "Table not found" with camelcase table & entity name

Using Spring Boot, with Spring Data JPA and H2 in-memory database (in PostgreSQL mode if it makes a difference).
I have a table & entity class named ContentBlock, yet H2 is complaining about missing CONTENT_BLOCK table, when I do a findAll() or findOne():
org.h2.jdbc.JdbcSQLException: Table "CONTENT_BLOCK" not found
I'm not sure if uppercase/camelcase makes a difference, but where does the underscore in CONTENT_BLOCK come from?
In my schema definition:
CREATE TABLE ContentBlock (
id BIGSERIAL PRIMARY KEY,
content TEXT
-- etc
);
And in the entity class:
#Entity
#Table(name = "ContentBlock")
public class ContentBlock {
// ...
}
(Of course I first tried without #Table annotation, as the class name exactly matches the table name.)
With my other tables/entities, with names like Asset, there are no problems, and I don't need to explicitly specify the table name on Java side:
#Entity
public class Asset {
// ...
}
In my setup, the H2 datasource is explicitly defined like this:
#Bean
public DataSource devDataSource() {
return new EmbeddedDatabaseBuilder()
.generateUniqueName(true)
.setType(EmbeddedDatabaseType.H2)
.setScriptEncoding("UTF-8")
.ignoreFailedDrops(true)
.addScripts("database/init.sql", "database/schema.sql", "database/test_data.sql")
.build();
}
(Contents of init.sql is SET MODE PostgreSQL;)
As workaround, I just renamed the ContentBlock table to Block in schema.sql, with #Table(name = "Block") in the Java class which I still call ContentBlock.
But this is weird, surely you can map a table with camelcase name to an entity somehow?
By default Spring Boot uses SpringNamingStrategy. It extends org.hibernate.cfg.ImprovedNamingStrategy from Hibernate 4. ImprovedNamingStrategy generates underscores in table names.
To map a table with camel case name to an entity you can use org.hibernate.cfg.EJB3NamingStrategy or implement your own.
An example of set a name strategy using properties
spring.jpa.hibernate.naming_strategy=org.hibernate.cfg.EJB3NamingStrategy

Hibernate query.list() is slower than HibernateTemplate.find()

We upgraded our project from Spring 3x/Hibernate 3x to Spring 4.1.5/Hibernate 4.3.8.
Initially we were using Hibernate Tempate. During upgrade we removed the Hibernate Template of spring and used Spring's declarative transaction management.
Earlier our query with hibernateTemplate used to take very sort time to retrive 3500 records from DB. Now when are using query.list(), the running time is coming in minutes (4-5 mins approx).
Old Code
DAO Class:
---------
public List<LatestRecVO> getListRecs(String listId) {
HibernateTemplate ht = new HibernateTemplate(getSessionFactory());
List<LatestRecVO> listOfRecs = ht.find(" from LatestRecVO a where a.listId = ? order by a.listRecId asc", Long.valueOf(listId) );
return listOfRecs;
}
Service Class:
--------------
#Transactional
public List<LatestRecVO> getListRecs(String listId) {
List<LatestRecVO> listOfRecs = listDao.getListRecDetails(listId);
return listOfRecs;
}
New Code
DAO Class:
---------
public List<LatestRecVO> getListRecs(String listId) {
Query q = getSession().createQuery(" from LatestRecVO a where a.listId = (:listId) order by a.listRecId asc");
q.setParameter("listId", Long.valueOf(listId));
List<LatestRecVO> listOfRecs = q.list();
return listOfRecs;
}
Service Class:
--------------
#Transactional
public List<LatestRecVO> getListRecs(String listId) {
List<LatestRecVO> listOfRecs = listDao.getListRecDetails(listId);
return listOfRecs;
}
The entity class LatestRecVO do not have any associated entity with it.
I checked the Hibernate Template's find() method and saw its uses some caching.
Tried 2nd level cache along with query cache but it didnt helped. I may have configured 2nd level cache incorrectly but to try it again i want to be sure that its the way out else i would be wasting time.
I made show_sql as true and can see it just ran a singly query. On DB the same query takes some milliseconds to run. It seems like hibernate is taking time to build objects from the result.
On one of the post it was mentioned that its mandate to have a default constructor in our entities. I have not created any constructor in my entity class so i assume that i do have java's default constructor in place.
My table has 36 columns and in total there are 4k records to be fetched.
Any pointer in this will be really helpful.
Update
Sorry, I cannot post the complete code here, so just giving the details. I have the composite primary key for LatestRecVO. I have created a class LatestRecPK for primary key, it implements serializable and have #Embeddable annotation. In LatestRecVO i have given #IdClass(LatestRecPK.class) to include the primary key class. LatestRecVO has a CLOB property along with String, Long and #Temporal(TemporalType.DATE) properties and corresponding setters/getters.

Resources