2

CRUD メソッドで使用するセッション ファクトリからセッションを取得しようとしています。コンストラクターでセッションを設定しようとしましたが、それまでに Bean が初期化されていません。Bean の作成後に初期化するにはどうすればよいですか?

スタックトレース

Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userDaoImpl' defined in file [/home/ryan/workspace/com-byteslounge-spring-tx/target/classes/com/byteslounge/spring/tx/dao/impl/UserDaoImpl.class]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [com.byteslounge.spring.tx.dao.impl.UserDaoImpl]: Constructor threw exception; nested exception is java.lang.NullPointerException
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1011)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:957)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:490)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:461)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:607)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
    at com.byteslounge.spring.tx.Main.main(Main.java:19)
Caused by: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [com.byteslounge.spring.tx.dao.impl.UserDaoImpl]: Constructor threw exception; nested exception is java.lang.NullPointerException
    at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:163)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:87)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1004)
    ... 13 more
Caused by: java.lang.NullPointerException
    at com.byteslounge.spring.tx.dao.impl.UserDaoImpl.<init>(UserDaoImpl.java:24)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
    at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:148)
    ... 15 more

UserDaoImpl.java

package com.byteslounge.spring.tx.dao.impl;

import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.byteslounge.spring.tx.dao.UserDao;
import com.byteslounge.spring.tx.domain.User;

@Service
public class UserDaoImpl implements UserDao {

    @Autowired
    private SessionFactory sessionFactory;

    private Session session;

    public UserDaoImpl() {
        session = sessionFactory.getCurrentSession();
    }

    public SessionFactory getSessionFactory() {
        return this.sessionFactory;
    }

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    public void insertUser(User user) {
        session.save(user);
    }

    public void removeUserByName(String username) {
        User user = null;
        try {
            getUser(username);
        } catch (IndexOutOfBoundsException e) {
            System.out.println(username + " does not exist!");
        } finally {
            if (user != null)
                session.delete(user);
        }
    }

    public User getUserById(int userId) {
        return (User) session.get(User.class, userId);
    }

    public User getUser(String username) {
        // Query query = sessionFactory.getCurrentSession().createQuery("from User where username = :username");
        // query.setParameter("username", username);

        Query query = session.getNamedQuery(User.FIND_USER_BY_USERNAME).setString("username", username);
        return (User) query.list().get(0);
    }

    @SuppressWarnings("unchecked")
    public List<User> getUsers() {
        Criteria criteria = session.createCriteria(User.class);
        return criteria.list();
    }
}

applicationContext.xml

<?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:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd 
                        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">

    <tx:annotation-driven />

    <context:component-scan base-package="com.byteslounge.spring.tx.dao.impl" />
    <context:component-scan base-package="com.byteslounge.spring.tx.user.impl" />

    <bean
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location">
            <value>database.properties</value>
        </property>
    </bean>

    <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.password}" />
    </bean>

    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource"></property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
                <prop key="hibernate.show_sql">true</prop>
            </props>
        </property>
        <property name="packagesToScan" value="com.byteslounge.spring.tx.domain" />
    </bean>

    <bean id="transactionManager"
        class="org.springframework.orm.hibernate4.HibernateTransactionManager"
        p:sessionFactory-ref="sessionFactory">
    </bean>

</beans>
4

2 に答える 2

3

@PostConstructタグを使用して、セッションを取得します。Bean はUserDaoImplが作成された後にのみ注入され、@PostConstructメソッドはすべての Bean が注入された後にのみ Spring によって呼び出されます。

@Service
public class UserDaoImpl implements UserDao {

    @Autowired
    private SessionFactory sessionFactory;

    private Session session;

    public UserDaoImpl() {
    }

    @PostConstruct
    public void init() {
        this.session = sessionFactory.getCurrentSession();
    }
    ...
}

もう1つの方法(私の意見ではより良い)は、コンストラクターによって注入し、必要なときにのみ現在のセッションを取得することです。

    ...
    private final SessionFactory sessionFactory;

    @Autowired
    public UserDaoImpl(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    private Session currentSession() {
        return this.sessionFactory.getCurrentSession();
    }

編集: できれば2番目の方法を使用してください。構築後にのみセッションを取得すると、そのセッションが期限切れになるとDAOへの呼び出しが機能しなくなるためです。SessionFactory#getCurrentSession()トランザクション メソッドで make 呼び出しを開始するときに常に使用します。

于 2013-05-23T21:28:56.520 に答える