The joy of Hibernate
For tasks not on a critical load/performance path I often find Hibernate handy to whip together some simple data access, particularly for simple CRUD. However, being a bungling buffoon I usually mess up my Hibernate mapping, setup queries that refer to non-existent properties, and so on. Naturally I aspire to resolve this by having automated tests of my DB code.
Testing DB code is often painful with any significant number of people. Often you either need every developer to have their own database, with it's own uniquely inconsistent data and ways of failing, or to use a shared database in which case people often manage to produce tests that don't work if more than one person runs the tests concurrently. Also testing on a "real" DB is slow and subject to failure for reasons not related to your code. To give a few of many examples, Joe removes columns at random, Wendy has a gift for locking tables, Tim has a test replication setup that doesn't work and stops his tests from running, Alice writes tests that only work if run in the correct order (Test B presumes data from test A still exists), and the continuous integration system doesn't have a DB of it's very own. Also the DBA randomly shuts down the shared DB and causes everyone's tests to fail.
So, let's try to set ourselves up so our tests can't share data, run fast, yield consistent results, and are not subject to external changes (like a common database changing) causing them to break. Our goal is that we spin up a new, clean, in-memory database for each test, run the test, and then dump the in-memory db.
In this article I walk through a complete test setup using Spring 3.1, Hibernate 4, and HSQLDB in a Maven project using Eclipse (with Maven Integration for Eclipse) as an editor. I built a fairly similar setup (same idea but built with Ant and Ivy) for tests on some projects I work with at my day job with considerable success so perhaps this will be helpful to someone else.
A significant portion of the post is devoted to setting up the project with dependencies, Hibernate configuration, Spring configuration, and all the other nonsense accompanying a modern Java project. Feel free to skip to the final section if you just want to glance over how the in-memory testing is wired in.
Basic Project Setup
Create a new Java Project (force of habit; I never remember the 'new Maven project option until too late, including when blogging):
Setup Maven style folders:
- Delete the 'src' folder
- Create four new source folders
- src/main/java
- src/main/resources
- src/test/java
- src/test/resources
Your project should look something like this:
Now right-click the project and choose Configure>Convert to Maven Project. Use the default values for Maven setup:
Now you have a pom.xml in the root of your project where you can setup dependencies and compilation options. The first change we want to make is to tell our project to build with Java 1.6 so we can use the spiffy @Resource annotation in our tests:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>InMemoryDbTests</groupId> <artifactId>InMemoryDbTests</artifactId> <version>0.0.1-SNAPSHOT</version> <build> <plugins> <!-- Please be a Java 1.6 application --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.0.2</version> <configuration> <source>1.6</source> <target>1.6</target> </configuration> </plugin> </plugins> </build> </project>
Now we're ready for dependencies.
Dependencies
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>InMemoryDbTests</groupId> <artifactId>InMemoryDbTests</artifactId> <version>0.0.1-SNAPSHOT</version> <dependencies> <!-- hibernate is a core part of the exercise --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>4.1.7.Final</version> </dependency> <!-- connection pooling --> <dependency> <groupId>commons-dbcp</groupId> <artifactId>commons-dbcp</artifactId> <version>1.4</version> </dependency> <!-- for the Spring org.springframework.orm.hibernate4.LocalSessionFactoryBean --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>3.1.2.RELEASE</version> </dependency> <!-- we want Spring --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>3.1.2.RELEASE</version> </dependency> <!-- we want Spring to manage our transactions --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>3.1.2.RELEASE</version> </dependency> <!-- Spring annotations work via proxies which use CGLIB --> <dependency> <groupId>cglib</groupId> <artifactId>cglib-nodep</artifactId> <version>2.2.2</version> </dependency> <!-- TEST DEPENDENCIES --> <!-- provides the Spring JUnit test runner & @ContextConfiguration --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>3.1.2.RELEASE</version> <scope>test</scope> </dependency> <!-- to run our tests with --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.10</version> <scope>test</scope> </dependency> <!-- our in-memory database provider --> <dependency> <groupId>org.hsqldb</groupId> <artifactId>hsqldb</artifactId> <version>2.2.8</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <!-- Please be a Java 1.6 application --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.0.2</version> <configuration> <source>1.6</source> <target>1.6</target> </configuration> </plugin> </plugins> </build> </project>If you think this is not strictly simple nor particularly obvious I would say you are right. http://mvnrepository.com/ is your friend if you know you want a dependency (say Spring test) but don't know the exact artifact, version, or what have you for it.
Data Access Configuration
OK, so we've got all our dependencies. Now we're ready to setup for our tests. Let us hypothesize that:
- in src/main/resources we have persistence.xml, a Spring file that defines our key data access beans
- A data source bean named "dataSource"
- A session factory named "sessionFactory"
- A transaction manager, in this case the Spring Hibernate 4 Transaction manager
- Applied automatically via Spring's annotation-driven transaction management
- The key properties of all beans are set via properties
- in src/main/resources we have db.properties
- This specifies the DB driver, URL, password, and so on
For test purposes we could override the data source and/or session factory completely, but because we factored out most of the key settings into properties we can just override a few key values from db.properties at test time.
On to the gory details. Create a persistence.xml file in src/main/resources with the following content:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd"> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${jdbc.driverClassName}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.pwd}"/> <property name="defaultAutoCommit" value="${jdbc.defaultAutoCommit}"/> <property name="accessToUnderlyingConnectionAllowed" value="${jdbc.accessToUnderlyingConnectionAllowed}"/> <property name="initialSize" value="${jdbc.initialSize}"/> <property name="maxActive" value="${jdbc.maxActive}"/> <property name="maxIdle" value="${jdbc.maxIdle}"/> <property name="minIdle" value="${jdbc.minIdle}"/> <property name="maxWait" value="${jdbc.maxWait}"/> <property name="validationQuery" value="${jdbc.validationQuery}"/> <property name="testOnBorrow" value="${jdbc.testOnBorrow}"/> <property name="testOnReturn" value="${jdbc.testOnReturn}"/> <property name="testWhileIdle" value="${jdbc.testWhileIdle}"/> <property name="timeBetweenEvictionRunsMillis" value="${jdbc.timeBetweenEvictionRunsMillis}"/> <property name="numTestsPerEvictionRun" value="${jdbc.numTestsPerEvictionRun}"/> <property name="minEvictableIdleTimeMillis" value="${jdbc.minEvictableIdleTimeMillis}"/> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="mappingResources"> <list> <value>hibernate-mapping.xml</value> </list> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">${hibernate.dialect}</prop> <prop key="hibernate.hbm2ddl.auto">none</prop> <prop key="hibernate.connection.release_mode">auto</prop> <prop key="hibernate.show_sql">${hibernate.showSql}</prop> <prop key="hibernate.format_sql">true</prop> <prop key="hibernate.use_sql_comments">true</prop> <prop key="hibernate.generate_statistics">true</prop> <prop key="hibernate.jdbc.use_scrollable_resultset">true</prop> <prop key="hibernate.jdbc.use_streams_for_binary">true</prop> <prop key="hibernate.jdbc.batch_size">${hibernate.batchSize}</prop> <prop key="hibernate.cache.region_prefix">hibernate.cache</prop> <prop key="hibernate.cache.use_query_cache">false</prop> <prop key="hibernate.cache.use_second_level_cache">false</prop> </props> </property> </bean> <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <tx:annotation-driven transaction-manager="transactionManager" /> </beans>
Next, create a db.properties file in src/main/resources with the following (obviously dummy; we don't care about the "real" db connection setup for this example) values:
jdbc.driverClassName=DB DRIVER CLASS, SAY SQL OR ORACLE jdbc.url=SOME DB URL jdbc.username=USERNAME jdbc.pwd=PWD jdbc.defaultAutoCommit=false jdbc.accessToUnderlyingConnectionAllowed=false jdbc.initialSize=5 jdbc.maxActive=100 jdbc.maxIdle=-1 jdbc.minIdle=${jdbc.initialSize} jdbc.maxWait=15000 jdbc.validationQuery=SELECT DATE OR SOMETHING jdbc.testOnBorrow=true jdbc.testOnReturn=false jdbc.testWhileIdle=false jdbc.timeBetweenEvictionRunsMillis=-1 jdbc.numTestsPerEvictionRun=3 jdbc.minEvictableIdleTimeMillis=1800000 hibernate.dialect=A DIALECT hibernate.showSql=false #0 = off hibernate.batchSize=0In reality some of these would vary by environment (DB URL, user/pwd for sure) and might want to be further externalized rather than bundled in here.
Hibernate Configuration
We need some sort of Hibernate entity we can use to create a sample in-memory test. We'll setup a simplified person class and map it. In src/main/resources create hibernate-mapping.xml with the following mapping:
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.blogspot.whileonefork.domain"> <class name="com.blogspot.whileonefork.domain.Person" table="people"> <id name="id" type="long" column="id" unsaved-value="0"> <generator class="identity"/> </id> <property name="firstName" column="first_name" /> <property name="lastName" column="last_name" /> </class> </hibernate-mapping>
In src/main/java in the com.blogspot.whileonefork.domain create the Person class:
package com.blogspot.whileonefork.domain; public class Person { private Long id; private String firstName; private String lastName; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } }
Finally we'll make ourselves a simple helper class to manage transactions and encapsulate simple CRUD operations. In src/main/java in the com.blogspot.whileonefork.db package create DaoAid.java with the following content:
package com.blogspot.whileonefork.db; import java.util.List; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.criterion.Criterion; import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; public class DaoAid { private static final int MAX_RESULT_SIZE = 128; private SessionFactory sessionFactory; public SessionFactory getSessionFactory() { return sessionFactory; } public void setSessionFactory(SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; } private Session getSession() { return sessionFactory.getCurrentSession(); } @Transactional(isolation = Isolation.READ_UNCOMMITTED, propagation = Propagation.REQUIRED) public <T> List<T> list(Class<T> classOfT, List<? extends Criterion> criteriaList, int maxResults) { if (null == classOfT) { throw new IllegalArgumentException("classOfT"); } if (maxResults < 1) { throw new IllegalArgumentException("maxResults must be >= 1"); } Session session = getSession(); org.hibernate.Criteria criteria = session.createCriteria(classOfT); criteria.setMaxResults(Math.min(maxResults, MAX_RESULT_SIZE)); if (null != criteriaList) { for (Criterion criterion : criteriaList) { criteria.add(criterion); } } @SuppressWarnings("unchecked") List<T> list = criteria.list(); return list; } @Transactional(isolation = Isolation.READ_UNCOMMITTED, propagation = Propagation.REQUIRED) public <T> T findById(Class<T> classOfT, long id) { @SuppressWarnings("unchecked") T result = (T) getSession().get(classOfT, id); return result; } @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED) public <T> T write(T instance) { @SuppressWarnings("unchecked") T savedInstance = (T) getSession().merge(instance); return savedInstance; } @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED) public <T> void delete(T instance) { getSession().delete(instance); } }
In Memory Testing
At long last we find our way to the point, doing some Hibernate operations against an in-memory database. We want to verify we can interact with a clean database for each test. We'll create a base class that sets up and tears down our in-memory database before/after each test, then write a simple test to do some data access to show it all works.
First of all, our base class for in-memory tests. In src/test/java, in the com.blogspot.whileonefork.db package, create InMemoryDbTestBase.java with the following content:
We have slapped @ContextConfiguration onto InMemoryDbTestBase so we need a Spring file to setup the beans for the test. Create src/test/resources/com/blogspot/whileonefork/db/InMemoryDbTestBase-context.xml with the following content:
First of all, our base class for in-memory tests. In src/test/java, in the com.blogspot.whileonefork.db package, create InMemoryDbTestBase.java with the following content:
package com.blogspot.whileonefork.db; import java.sql.Connection; import javax.annotation.Resource; import javax.sql.DataSource; import org.hibernate.cfg.Configuration; import org.hibernate.tool.hbm2ddl.SchemaExport; import org.junit.After; import org.junit.Before; import org.springframework.orm.hibernate4.LocalSessionFactoryBean; import org.springframework.test.context.ContextConfiguration; @ContextConfiguration public class InMemoryDbTestBase { //&: get the actual factory, not the object it produced @Resource(name="&sessionFactory") private LocalSessionFactoryBean sf; @Resource private DataSource dataSource; private Configuration cfg; private Connection conn; @Resource private DaoAid daoAid; @Before public void setup() throws Exception { if (null == cfg) { if (null == sf) { throw new IllegalStateException("No LocalSessionFactoryBean; perhaps you didn't setup @RunWith and @ContextConfiguration on your test?"); } cfg = sf.getConfiguration(); } conn = dataSource.getConnection(); SchemaExport exporter = new SchemaExport(cfg, conn); exporter.execute(true, true, false, true); if (null != exporter.getExceptions() && exporter.getExceptions().size() > 0) { throw new IllegalStateException("Unable to setup schema; export failed"); } } @After public void teardown() throws Exception { //see http://hsqldb.org/doc/guide/running-chapt.html#rgc_closing_db if (null != conn) { conn.createStatement().execute("SHUTDOWN"); conn.close(); conn = null; } } public DaoAid getDaoAid() { return daoAid; } public void setDaoAid(DaoAid daoAid) { this.daoAid = daoAid; } }Creating a new connection to the HSQLDB will spin up a new, blank, database. The SchemaExport class will then create schema to match our hibernate mapping. Finally in teardown, run after each test, we shutdown the database which will release the in-memory db.
We have slapped @ContextConfiguration onto InMemoryDbTestBase so we need a Spring file to setup the beans for the test. Create src/test/resources/com/blogspot/whileonefork/db/InMemoryDbTestBase-context.xml with the following content:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd"> <!-- for an in-memory test we need to load the db properties, then the test properties, then the persistence bits --> <context:property-placeholder location="classpath:db.properties, classpath:db.inmemory-overrides.properties"/> <import resource="classpath:/persistence.xml" /> </beans>Note that we load db.properties before db.inmemory-overrides.properties. This allows db.inmemory-overrides.properties to overwrite any properties of the same name in db.properties. We then import persistence.xml, which will load using the in memory db driver and connection URL. We only need to replace a few properties. Create src/test/resources/db.inmemory-overrides.properties with the following content:
jdbc.driverClassName=org.hsqldb.jdbcDriver jdbc.url=jdbc:hsqldb:mem:unittestdb jdbc.username=sa jdbc.pwd= jdbc.validationQuery=values(current_timestamp) hibernate.dialect=org.hibernate.dialect.HSQLDialect hibernate.showSql=trueSo, we should now be able to author a test that does some data access and verifies that it operates on a clean database. Create PersonListOfOneTest.java in src/test/java, in the com.blogspot.whileonefork.domain package with the following content:
package com.blogspot.whileonefork.domain; import static org.junit.Assert.assertEquals; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.blogspot.whileonefork.db.InMemoryDbTestBase; /** * Save an item and list Person's with no criteria, twice. * Should both see 1 item because DB is scrubbed each time. * */ @RunWith(SpringJUnit4ClassRunner.class) public class PersonListOfOneTest extends InMemoryDbTestBase { @Test public void list1() { assertEquals(0, getDaoAid().list(Person.class, null, 8).size()); getDaoAid().write(new Person()); assertEquals(1, getDaoAid().list(Person.class, null, 8).size()); } @Test public void list2() { assertEquals(0, getDaoAid().list(Person.class, null, 8).size()); getDaoAid().write(new Person()); assertEquals(1, getDaoAid().list(Person.class, null, 8).size()); } }Execute the test; it should pass. This means our code successfully:
- Created a connection to a new HSQLDB in-memory instance for each test
- Ran the Hibernate SchemaExport to build the desired table structure to allow data access
- Wrote a record into the in-memory database and loaded it back
If the in-memory database wasn't getting cleaned up between tests then the second test to execute would return two records from the call to list(). Mission accomplished!
Your final project should look like this:
In practice I have used a similar approach to test both simple and complex data access across a large project with an extensive test suite executing fast and with reliable results and near elimination of problems involving data access.
64 comments:
Great thanks for the bpost
Thanks for the blogpost. It really gave me a kickstart of setting up my testcase with an in-memory DB.
I did ran into a couple of problems while running it, but fixed it while I was going along:
1. Added @RunWith(SpringJUnit4ClassRunner.class) in the InMemoryDbTestBase class.
2. @Resource(name="daoAid") on the daoAid variable.
3. Added an daoAid bean in the persistence.xml.
Cheers, Chee-Hong
Hi, thanks for posting this article! Just wondering if you setup a code for download?
Very useful article.
I published fully fonctional projects here:
https://github.com/atao60/spring-examples/tree/master/spring-database/spring-database-test
I enjoyed reading this and viewing the selection of featured sites. Thanks for taking the time to put it all together.
free wordpress themes
blog Wordpress themes
great information.
Thanks for posting.
keep sharing.
best software testing training in bangalore
When you buy a new HP printer, you try to connect it using the user manual. The manual provided by the 123.hp.com/setup manufacturer may not be in detail. Hence, our technical experts have given simple instructions that guide you through the HP Printer setup and troubleshooting issues if any. We also offer free 123hp driver (Both Basic and Full-feature) to make your printer function efficiently. The navigation is too easy such that all instructions are available on one single page. www.123.hp.com/setup
Apakah kalian pernah mendapatkan Kartu AK dan anda melakukan ALL-in dan pada akhirnya anda kalah dengan kartu lawan anda yang hanya bernilai 2 dan 3
asikqq
http://dewaqqq.club/
http://sumoqq.today/
interqq
pionpoker
bandar ceme
freebet tanpa deposit
paito warna terlengkap
syair sgp
Hi, the post which you have provided is fantastic, I really enjoyed reading your post, and hope to read more. thank you so much for sharing this informative blog.
mcafee.com/activate | mcafee.com/activate
I like your explanation of topic and ability to do work.I really found your post very interesting .
Install Kaspersky with Activation Code | Reinstall Kasperksy Total Security | Kaspersky Help & Support Service | Kaspersky Installation Error
Thank for important information . I like your explanation of topic and ability to do work.I really found your post very interesting .
Activation.kaspersky.com | Kaspersky activation code | Aol Support | Install Kaspersky with Activation Code
Thank you so much for this Post and all the best for your future. You are really a talented person I have ever seen. I am satisfied with the arrangement of your post.
Brother printer offline
Brother Printer Support Number
The article has actually peaks my interest. I am going to bokmarks your web site and maintain checking for brand new information.
Dell Customer Service
Dell Customer Support
It's very informative and you are obviously very knowledgeable in this area. You have opened my eyes to varying views on this topic with the interesting and solid content.
Dell Support Assistant
Welcome to RealPrinterFix247 right place to online help for HP Printer Tech Support Phone Number offered by best technicians to resolve any issues with HP computers, laptops, printers, desktop, and alternative parable devices, etc. We are remote HP Printer Tech support services for HP users facing a totally different level of technical problems with their Hewlett Packard Enterprise devices like Desktop Computers, Laptops, Printers, Scanners and Tablets business customer support.
Canon Printer Tech Support Phone Number | QuickBooks Tech Support Phone Number | Norton Tech Support Phone Number
Thanks for giving me a great kind of information. So useful and practical for me. Thanks for your excellent blog, nice work keeps it up thanks for sharing the knowledge.
How to reset your Wireless Router successfully
Thank for important information . I like your explanation of topic and ability to do work.I really found your post very interesting .
Netflix Password Reset
You have performed a great job on this article. It's very precise and highly qualitative. You've managed to make it readable and easy to read. You have some real writing talent. Thank you so much.
Dell Command Update
Are you facing problems while signing-in at your Aol page ? On this page you can get all basic information like www.mail.aol.com login, How to recover an Aol email account & How to create an Aol email account ? You can also chat with AOL Live experts for all your AOL needs from email to login, technical questions, mobile email, and more ? Call our helpline number to fix your problems now!
www.mail.aol.com login
Nice post!! Thanks for sharing...
Python Training in Bangalore
I really happy found this website eventually Really informative and inoperative, Thanks for the post and effort! Please keep sharing more such blog www.avg.com/retail
avg.com/retail
The information you shared with us was very helpful, thank you very much. Great post, Thanks for providing us this great knowledge, Keep it up mcafee.com/activate
It is a very helpful and informative blog post. I would like to thank to you for providing such information I have also have a website providing very good information.
norton.com/setup
www.norton.com/setup
Good information
data science training in bangalore
reactjs training in bangalore
HP Printer drivers universal for Windows
HP printer software download for Windows
HP Printer drivers for Mac
HP Printer drivers for Windows 10
MyBlogger Club
Guest Posting Site
Best Guest Blogging Site
Guest Blogger
Guest Blogging Site
Thank for sharing with us,such a nice article and a lot of useful and informatics.
office.com/setup | office.com/setup | webroot.com/safe
Nice info about Hibernate technology.
mcafee.com/activate
Unleash the Future
Nice Article, Great experience for me by reading this info. Thanks for sharing the information with us.keep updating your ideas.
Looking for the best ppc course in Bangalore India? Learn PPC from Ranjan Jena, 10+ Years Expert Google Ads Trainer. 1000+ Students Trained @ eMarket Education, Koramangala, Bangalore.
Best Online Digital Marketing Courses in Bangalore, India
Best Digital Marketing Institute in Bangalore
Best digital marketing agency: Reflekt Visual Pvt Ltd one of the Best Digital Marketing Agency that offers Digital marketing services Proven to Increase Leads, Sales, & Revenue. It capitalizes on paid advertisements, sponsorships, and collaborations to put your page content where influential people will see them.
Visit Us: Reflekt Visual Pvt Ltd
Well done! Great article...
QuickBooks Error 3371 status code 11104
Sage 50 keeps asking to update
QuickBooks unable to complete this operations and needs to restart
Cannot connect to Sage 50 database on network
Proforma invoice QuickBooks
Sage 50 import and upload exiting data
How to transfer Sage 50 files to another computer
Find missing QuickBooks 2019 license and product number
Reached to maximum allowed connection to Sage 50
Sage will not accept correct password
Are you looking for a pankaj garg audit ca final classes then now go to the best platform smartnstudy they offer you all faculty lectures. Call us - 97688 94000
Get the basic guidelines to use and manage the Venmo login account. The manual instructions are provided to access the Venmo account on your compatible devices.
Venmo Login | Venmo Login
This informative read is focused on transferring your AOL Mail contacts to your Gmail account for ease, reliability and fast accessibility world-wide.
AOL Mail Login | AOL Mail Login
Learn the basic steps to access open hp printer software website without interruptions. Follow the quick and basic steps to deal with the error in the hp printer. Our experts are there for you round the clock for resolving your problems.
Open HP Printer Software | HP Support Solutions Framework | HP Officejet 4650 Wireless Setup
Such a very useful article. Very interesting to read this article. I would like to thank you for the efforts you had made for writing this awesome article.
UI UX Design Company
thanks for this amazing blog
keep sharing
full stack developer course
job guaranteed courses in bangalore
"To successfully install and setup HP printers via 123.hp.com, follow the steps are Unpack the device,When you get your HP printer bundle, place in the chose position, and move further
123.hp.com/setup | HP Printer Assistant
"
If you need any help or want to know more about norton.com/setup install feel free to reach out.
Thanks for sharing article.
Best Timesheet Software in Bangalore
Zenetial will be the best Employee timesheet management software in Bangalore. It can easily track the remote employee's data. Get a free demo and easy to use.
If your HP Printer offline fix meaning it's ineffective to speak together with your package. however don’t worry! this can be one in every of the foremost common HP printer problems which is why we have a tendency to area unit continuously prepared for solutions that may amendment the standing of your HP printer from offline to on-line
If you're aware of your AOL email account password and wish to vary it to strengthen your account’s privacy merely, you'll be able to do therefore by following some easy steps. ever-change aol password needs you to use the new password within the login credentials section of the AOL sign-in page
Usually I never comment on blogs but your article is so convincing that I never stop myself to say something about it. Just have a look at this Cabin Crew Training Centre
You can watch any one TV device at one location at one time. It facilitates the streaming of compatible TV devices from any of the locations. Fubo TV activate code is the code that is present on your TV screen. Open the app store on your TV, look for Fubo TV. Now open the app, an activation code comes. fubo tv connect enter code
Watching FuboTv on your smart tv relies upon on what gadget you are using. Some smart TV helps the picks to assist viewers with effortless fubo TV sign, using the on-screen keyboard to kind username and password and then log in indirectly.All first-time users have first to activate their account and preform Fubo Tv Account login. fubotv connect code
cash app is a online money transfer service . It is available for only mobile application.If you want to send money and receive money securely and quickly . if you want to know about cash app refund process then you can contact cash app customer support. I will provide best solution for your queries.
nice post..
Learn German | German Learning | German Classes near me
Thanks for sharing such a nice Blog.
Permanent Cure for HIV in India | HIV Cure in India
Such an ideal piece of blog. It’s quite interesting to read content like this. I appreciate your blog
Best Homecare Services in Bangalore
caregiver services in bangalore
Wonderful blog! Thanks for the information,
renewable energy
PLC and SCADA Training Institute in Gurgaon
Thank you for this beautiful information
Coaching Centre In Bangalore
Java Training In Bangalore
Training Institute In Marathahalli
Java Training In Marathahalli
thank you for the blog.
Java Training Institute in Chennai
Java Training Institutes in Bangalore
Java Training Institute in Coimbatore
Nice blog, Share more like this.
Full Stack Developer Course In Chennai
Full Stack Developer Online Course
Full Stack Developer Course In Bangalore
Full Stack Developer Course in Coimbatore
Python is an object-oriented, analytic programming language. Classes, dynamically typed, high-level volatile data types, exceptions, modules, and exception management are all included. It supports various programming paradigms, including primary and reactive programming and object-oriented programming.Python Training in Chennai
Python Online Course
Python Training in Bangalore
Nice blog, it is very informative.
HR Training in Chennai
HR Course in Chennai
Great blog, keep sharing with us.
MSBI Training in Chennai
MSBI Online Training
Eimple Labs, a renowned IT company based in Bangalore, has partnered with YBN University to design a B.Tech, BCA & MCA Computer Science program that focuses on industry-demanding technology. Through this collaboration, Eimple Labs brings its expertise and industry insights to the table, ensuring that the curriculum remains relevant and up-to-date. With a strong emphasis on practical learning and hands-on experience, students are exposed to real-world projects and industry case studies.
BTECH in Software Engineering
BTECH in Artificial Intelligence
BCA in Software Engineering
MCA in Software Engineering
Interesting and informative blog content. Thanks a lot for sharing :-)
BroadMindM - IELTS coaching in Madurai and Chennai
Eimple Labs, a renowned IT company based in Bangalore, has partnered with YBN University to design a B.Tech, BCA & MCA Computer Science program that focuses on industry-demanding technology. Through this collaboration, Eimple Labs brings its expertise and industry insights to the table, ensuring that the curriculum remains relevant and up-to-date. With a strong emphasis on practical learning and hands-on experience, students are exposed to real-world projects and industry case studies.
thanks for valuable info
gcp training in hyderabad
"Great article! Using an in-memory database for unit testing in a Spring/Hibernate project is a really effective approach. I particularly appreciate how it speeds up the testing process and provides isolation from external dependencies like the actual database. The example code and explanations make it much easier to understand how to implement this in a real-world project. One thing I’d love to see explored further is how to handle more complex transactions or cascading operations in tests. Thanks for sharing such a helpful guide!"
Digital Marketing Course In Hyderabad
Nyc Article
Digital Marketing Course In Ameerpet
Post a Comment