Nullpointer exception while connecting to DB using MyBatis - java

I am having the following issue: when I am connecting to db using MyBatis I get an NPE.
Here is the class for setting connection:
public class SetDBConnection {
private Mapper mapper;
private SqlSession session;
private Configuration configuration;
public SetDBConnection() {
configuration = new Configuration();
configuration.setJdbcTypeForNull(JdbcType.VARCHAR);
configuration.setLogImpl(Slf4jImpl.class);
configuration.setDefaultExecutorType(ExecutorType.REUSE);
configuration.addMapper(Mapper.class);
Properties properties = null;
try {
properties = readProperties();
} catch (IOException e) {
e.printStackTrace();
}
configuration.setVariables(properties);
}
public Mapper openSession() {
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);
session = sqlSessionFactory.openSession();
mapper = session.getMapper(Mapper.class);
return mapper;
}
public void closeSession() {
session.commit();
session.close();
}
private Properties readProperties() throws IOException {
Properties properties = new Properties();
InputStream inputStream = getClass().getClassLoader()
.getResourceAsStream("connection.properties");
if (inputStream != null) {
properties.load(inputStream);
} else {
throw new FileNotFoundException("property file not found in the classpath");
}
inputStream.close();
return properties;
}
}
And here I call it and try to Insert data
SetDBConnection conn = new SetDBConnection();
Person p = new Person();
p.setName("Alex");
p.setLastName("Bondar");
p.setTelephone("+79267157256");
p.setPersonalId("777-216");
Mapper mapper=conn.openSession();
try {
System.out.println("All set to go");
mapper.saveOrUpdatePerson(p);
} finally {
conn.closeSession();
}
Stacktrace is the following:
Exception in thread "main" org.apache.ibatis.exceptions.PersistenceException:
### Error opening session. Cause: java.lang.NullPointerException
### The error may exist in org/abondar/experimental/mybatisdemo/mappers/Mapper.java (best guess)
### Cause: java.lang.NullPointerException
at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
at org.apache.ibatis.session.defaults.DefaultSqlSessionFactory.openSessionFromDataSource(DefaultSqlSessionFactory.java:100)
at org.apache.ibatis.session.defaults.DefaultSqlSessionFactory.openSession(DefaultSqlSessionFactory.java:47)
at org.abondar.experimental.mybatisdemo.SetDBConnection.openSession(SetDBConnection.java:51)
at org.abondar.experimental.mybatisdemo.Main.main(Main.java:19)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Caused by: java.lang.NullPointerException
at org.apache.ibatis.session.defaults.DefaultSqlSessionFactory.openSessionFromDataSource(DefaultSqlSessionFactory.java:95)
... 8 more
What can be wrong and is there any way not to re-establish DB-connection for every action(select,insert or delete)?

It seems you have no Environment and TransactionFactory defined. According to the docs you should initialize MyBatis somehow like this:
DataSource dataSource = BlogDataSourceFactory.getBlogDataSource();
TransactionFactory transactionFactory = new JdbcTransactionFactory();
Environment environment = new Environment("development", transactionFactory, dataSource);
Configuration configuration = new Configuration(environment);

Thanks Frank for DataSource idea. I used default pooled dataSource and this problem looks to be solved

Related

How to skip "information_schema.sequences" creation while using Hibernate in Java projects

I am using Redshift as a DB for my Java Project with Hibernate support. When the Hibernate starts, it tries to create a sequence, which I do not need.
public class HibernateUtil {
private static SessionFactory SESSION_FACTORY;
private static StandardServiceRegistry registry;
public static synchronized SessionFactory getSessionFactory(DataSource dataSource) {
if (SESSION_FACTORY == null) {
try {
Configuration configuration = new Configuration();
Properties settings = new Properties();
settings.put("show_sql", "false");
settings.put("current_session_context_class", "thread");
settings.put("hbm2ddl.auto", "none");
configuration.setProperties(settings);
registry = new StandardServiceRegistryBuilder()
.applySettings(configuration.getProperties())
.applySetting(Environment.DATASOURCE, dataSource)
.build();
SESSION_FACTORY = configuration.buildSessionFactory(registry);
} catch (Exception e) {
log.error("Error creating Session Factory.", e);
if (registry != null) {
StandardServiceRegistryBuilder.destroy(registry);
}
}
}
return SESSION_FACTORY; }
}
This is the stack trace.
ERROR [2019-06-07 14:41:40,743] org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentImpl: Could not fetch the SequenceInformation from the database
! com.amazon.support.exceptions.ErrorException: [Amazon](500310) Invalid operation: relation "information_schema.sequences" does not exist;
! ... 52 common frames omitted
! Causing: java.sql.SQLException: [Amazon](500310) Invalid operation: relation "information_schema.sequences" does not exist;
I created a custom Dialect that overrode existing PostgreSqlDialect
public class CustomRedshiftDialect extends PostgreSQL81Dialect {
#Override
public String getQuerySequencesString() {
return null;
}
}
And in the HibernateUtil class or the appropriate XML.
// Hibernate settings equivalent to hibernate.cfg.xml's properties
Properties settings = new Properties();
settings.put("show_sql", "false");
settings.put("current_session_context_class", "thread");
settings.put("hbm2ddl.auto", "none");
settings.put("hibernate.dialect", "com.me.vlimbare.factory.db.CustomRedshiftDialect");

How to use getCurrentSession in Hibernate?

Configuration hibernate
Properties prop= new Properties();
prop.setProperty("hibernate.connection.driver_class", "com.mysql.jdbc.Driver");
prop.setProperty("hibernate.connection.url", url);
prop.setProperty("hibernate.connection.username", user);
prop.setProperty("hibernate.connection.password", password);
concreteSessionFactory = new AnnotationConfiguration()
.addPackage("Main.*")
.addProperties(prop)
.addAnnotatedClass(DeviceDataSet.class)
.buildSessionFactory();
public SessionFactory sessionFactory() {
return concreteSessionFactory;
}
I use
public long insertNewJournalNote(JournalDataSet journalDataSet) {
Session session = sessionFactory.openSession();
MySqlDAO dao = new MySqlDAO(session);
return dao.insertNewJournalNote(journalDataSet);
}
With getCurrentSession, I get:
Exception in thread "main" org.hibernate.HibernateException: No CurrentSessionContext configured
Maybe this line could solve your problem:
prop.setProperty("hibernate.current_session_context_class", thread);

java.lang.NoSuchFieldError: namingStrategy

There's an example from the web on how to use annotations in Hibernate (before that I've worked on the same example, but it used .xml instead. And I've managed to make it work without exceptions).
So now I have:
Initial session factory creation failedjava.lang.NoSuchFieldError: namingStrategy
Exception in thread "main" java.lang.ExceptionInInitializerError
at firstproject.HibernateUtil.<clinit>(HibernateUtil.java:14)
at firstproject.StudentDAO.addSubject(StudentDAO.java:82)
at firstproject.Test.main(Test.java:12) Caused by: java.lang.NoSuchFieldError: namingStrategy
at org.hibernate.cfg.AnnotationConfiguration.reset(AnnotationConfiguration.java:250)
at org.hibernate.cfg.Configuration.<init>(Configuration.java:125)
at org.hibernate.cfg.Configuration.<init>(Configuration.java:119)
at org.hibernate.cfg.AnnotationConfiguration.<init>(AnnotationConfiguration.java:108)
at firstproject.HibernateUtil.<clinit>(HibernateUtil.java:11)
... 2 more
Here is some code, that may help:
public class HibernateUtil {
private static final SessionFactory sessionFactory;
static {
try {
sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory(); // HibernateUtil.java:11
} catch (Throwable ex) {
System.err.println("Initial session factory creation failed" + ex);
throw new ExceptionInInitializerError(ex); // HibernateUtil.java:14
}
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
}
public class StudentDAO {
public Long addSubject(Subject subject) {
Session session = HibernateUtil.getSessionFactory().getCurrentSession(); // StudentDAO.java:82
session.beginTransaction();
Long result = (Long) session.save(subject);
session.getTransaction().commit();
return result;
}
}
public class Test {
public static void main(String[] args) {
StudentDAO dao = new StudentDAO();
Subject subject = new Subject();
subject.setSubjectName("Mathematics");
dao.addSubject(subject); // Test.java:12
}
}
Hi Kleeo
You have written the following line in HibernateUtil class.
sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
Replace this line of code with the below written line & retry. I hope this will work for you.
sessionFactory = new Configuration().configure().buildSessionFactory();
AnnotationConfiguration has been Deprecated in Hibernate 3.6.
As you can see in the documentation (see link below) all functionality has been moved to Configuration.
You can use safely Configuration instead.
sessionFactory = new Configuration().configure().buildSessionFactory();
AnnotationConfiguration documentation:
http://docs.jboss.org/hibernate/core/3.6/javadocs/org/hibernate/cfg/AnnotationConfiguration.html
Use below :
sessionFactory = new Configuration().configure().buildSessionFactory();
And also ensure that your cfg.xml should be present in root of src folder. Else you will get exception of unable to find cfg file

HibernateException: hibernate.cfg.xml not found at root folder

I tried to run easy test for Hibernate testing but it fails:
public class TestService {
static {
PropertyConfigurator.configure("log4j.properties");
}
public static void main(String[] args) {
String mail = "lelyak#gmail.com";
User user = new UserService().getByEmail(mail);
System.out.println("user info: " + user.toString());
System.out.println("\nTHE END");
}
}
Here is output:
02:24:53,166 ERROR main HibernateUtil:<clinit>:24 - org.hibernate.HibernateException: hibernate.cfg.xml not found
Exception in thread "main" java.lang.NullPointerException
at com.lelyak.controller.dao.ElementDAOImpl.getAllElements(ElementDAOImpl.java:76)
at com.lelyak.controller.service.UserService.getListOfObjects(UserService.java:39)
at com.lelyak.controller.service.UserService.getByEmail(UserService.java:52)
at com.lelyak.application.TestService.main(TestService.java:17)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
HibernateUtil:
public class HibernateUtil {
private static Logger log = Logger.getLogger(HibernateUtil.class);
private static SessionFactory sessionFactory = null;
private static final Configuration configuration = new Configuration();
static {
try {
configuration.configure("hibernate.cfg.xml");
sessionFactory = configuration.buildSessionFactory(new ServiceRegistryBuilder()
.applySettings(configuration.getProperties())
.buildServiceRegistry());
} catch (Exception e) {
log.error(e);
}
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
}
cfg file is at project folder:
log4j.properties at the same location is readable. What is wrong with cfg file?
Any suggestion?
You would like to read the file present in folder WebContent,you could try to use likes this
InputStream st= getServletContext().getResourceAsStream("/hibernate.cfg.xml");
But I recommend to put hibernate.cfg.xml under src and your code
configuration.configure("hibernate.cfg.xml");
will be OK.
Hibernate pulls it's hibernate.cfg.xml from the class path rather than the file system. So if you put it in src or src\Java depending on your structure it should work.
You need to put your hibernate.cfg.xml under the src folder and in your code you can do this
configuration.configure();

NullPointerException trying to Autowire Service in Java Application (Spring)

I am writing a Java Application that is going to be using Spring, Hibernate and more its going to be packaged in a Jar and run from the command like.
My main class looks like the following right now:
public class App
{
private static final Logger logger = LoggerFactory.getLogger(App.class);
#Autowired
private static MemberInquiryService memberInquiryService;
public static void main(String[] args )
{
logger.info("Starting Inquiry Batch Process");
int pendingRecords = memberInquiryService.getPendingRecordCount();
logger.info("Current Number Of Pendinig Records (" + pendingRecords + ")");
logger.info("Ending Inquiry Batch Process");
}
}
and in the getPendingRecordCount I am just return "10" for testing:
public int getPendingRecordCount()
{
return 10;
};
Why would I be getting the following error:
Exception in thread "main" java.lang.NullPointerException
at org.XXXX.inquirybatch.app.App.main(App.java:33)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Also here is my DatabaseConfig.class
#Configuration
#EnableTransactionManagement
#ComponentScan(basePackages= { "org.xxxx.inquirybatch", "org.xxxx.core" })
#PropertySource("classpath:application.properties")
public class DatabaseConfig {
private static final Logger logger = LoggerFactory.getLogger(DatabaseConfig.class);
#Autowired
Environment env;
#Bean
public DataSource dataSource() {
String serverType = env.getProperty("server.type");
try {
if(serverType.equalsIgnoreCase("tomcat"))
{
com.mchange.v2.c3p0.ComboPooledDataSource ds = new com.mchange.v2.c3p0.ComboPooledDataSource();
ds.setDriverClass(env.getProperty("database.driver"));
ds.setUser(env.getProperty("database.user"));
ds.setPassword(env.getProperty("database.password"));
ds.setJdbcUrl(env.getProperty("database.url"));
return ds;
}
else
{
Context ctx = new InitialContext();
return (DataSource) ctx.lookup("java:jboss/datasources/mySQLDB");
}
}
catch (Exception e)
{
logger.error(e.getMessage());
}
return null;
}
#Bean
public SessionFactory sessionFactory()
{
LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean();
factoryBean.setDataSource(dataSource());
factoryBean.setHibernateProperties(getHibernateProperties());
factoryBean.setPackagesToScan(new String[] { "org.xxxx.inquirybatch.model", "org.xxxx.core.model" } );
try {
factoryBean.afterPropertiesSet();
} catch (IOException e) {
logger.error(e.getMessage());
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
return factoryBean.getObject();
}
#Bean
public Properties getHibernateProperties()
{
Properties hibernateProperties = new Properties();
hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
hibernateProperties.setProperty("hibernate.show_sql", env.getProperty("hibernate.show_sql"));
hibernateProperties.setProperty("hibernate.use_sql_comments", env.getProperty("hibernate.use_sql_comments"));
hibernateProperties.setProperty("hibernate.format_sql", env.getProperty("hibernate.format_sql"));
hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
hibernateProperties.setProperty("hibernate.generate_statistics", env.getProperty("hibernate.generate_statistics"));
hibernateProperties.setProperty("javax.persistence.validation.mode", env.getProperty("javax.persistence.validation.mode"));
//Audit History flags
hibernateProperties.setProperty("org.hibernate.envers.store_data_at_delete", env.getProperty("org.hibernate.envers.store_data_at_delete"));
hibernateProperties.setProperty("org.hibernate.envers.global_with_modified_flag", env.getProperty("org.hibernate.envers.global_with_modified_flag"));
return hibernateProperties;
}
#Bean
public HibernateTransactionManager hibernateTransactionManager()
{
HibernateTransactionManager htm = new HibernateTransactionManager();
htm.setSessionFactory(sessionFactory());
htm.afterPropertiesSet();
return htm;
}
}
Spring never injects static fields. And it only inject objects that are retrieved from the application context, or are themselves injected into other objects.
You're not even creating an application context in your program, so Spring doesn't play any role in this program.
I suggest to read the documentation.
You need to get the memberInquiryService from ClassPathXmlApplicationContext
For example :-
ApplicationContext context= new ClassPathXmlApplicationContext("spring config.xml");
MmberInquiryService memberInquiryService = context.getBean("memberInquiryService ");
basically in your code snippet MemberInquiryService is not spring managed as you are not getting from spring container. Also you need to declare MmberInquiryService entry in spring config.xml
I had to change the main class to..
public static void main(String[] args )
{
logger.info("Starting Inquiry Batch Process");
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
MemberInquiryService memberInquiryService = (MemberInquiryService) context.getBean("memberInquiryService");
int pendingRecords = memberInquiryService.getPendingRecordCount();
logger.info("Current Number Of Pendinig Records (" + pendingRecords + ")");
logger.info("Ending Inquiry Batch Process");
}

Categories