Блокировка в Hibernate

 
 
 
Сообщения:110
Не знаю почему но возникает блокировка при использовании hibernate. Как только добавил еще несколько методов доступа к БД.
Я подозреваю что проблема в Транзакциях. ТАк как не хочет выполняться transaction.commit() в методе getSpitterByUsername(String usernamea).
До того как добавил еще методов в HibernateSpitterDao.java этот - getSpitterByUsername(String usernamea) работал.

public class HibernateSpitterDao implements SpitterDao {
    private SessionFactory sessionFactory;
    private Session session;

    public HibernateSpitterDao(){}

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

    private Session currentSession() {
        return sessionFactory.getCurrentSession();
    }
	
public Spitter getSpitterByUsername(String usernamea) {

        List<Spitter> tempListSpitter = new ArrayList<>(1);
        Spitter spitter;

        try {
            session =   currentSession();
            final Transaction transaction = session.beginTransaction();
            try {
                System.out.println("transaction = " + transaction.toString());
				//SQL запрос работает, я проверил
                tempListSpitter = session.createQuery(
                        "from Spitter where username = ? ").
                        setString(0,usernamea).list();

                spitter = tempListSpitter.get(0);

                transaction.commit();
            } catch (HibernateException ex) {
                transaction.rollback();
                throw ex;
            }
        } finally {
            HibernateUtil.closeSession();
        }
        return spitter;
    }
.....
}

@Component
public class HibernateUtil {

    private static final ThreadLocal<Session> threadLocal = new ThreadLocal();


    public static void closeSession() throws HibernateException {
        Session session = (Session) threadLocal.get();
        threadLocal.set(null);

        if (session != null) {
            session.close();
        }
    }
}


Конфигурация:

<bean id="sessionFactory"
          class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="configLocation">
            <value>classpath:hibernate.cfg.xml</value>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="dialect">org.hibernate.dialect.HSQLDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.connection.charSet">UTF-8</prop>
            </props>
        </property>
    </bean>

	Данные для подключения к БД- все работает.	
	db.driver=org.hsqldb.jdbcDriver
	#db.url=jdbc:hsqldb:mem:spitter
	db.url=jdbc:hsqldb:hsql://localhost:9005/spitt
	db.username=sa
	db.password=
	db.vendor=hsql	

	<bean id="dataSource"
          class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${db.driver}"/>
        <property name="url" value="${db.url}"/>
        <property name="username" value="${db.username}"/>
        <property name="password" value="${db.password}"/>
    </bean>
	
	<bean id="transactionManager"
          class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>

    <!-- к каждому методу в классе Transactional применять совет с определением
    транзакции-->
    <tx:annotation-driven transaction-manager="transactionManager" />

Конфигурация Hibernate:

	<hibernate-configuration>
    <session-factory>
        <property name="connection.driver_class">org.hsqldb.jdbcDriver</property>
        <property name="connection.url">jdbc:hsqldb:hsql://localhost:9005/spitt</property>
        <property name="connection.username">sa</property>
        <property name="connection.password"></property>
        <property name="connection.pool_size">10</property>
        <property name="show_sql">false</property>
        <property name="dialect">org.hibernate.dialect.HSQLDialect</property>
        <property name="current_session_context_class">thread</property>
        <mapping resource="Spitter.hbm.xml" />
        <mapping resource="Spittle.hbm.xml" />
        <mapping resource="Views.hbm.xml" />
        <mapping resource="Topic.hbm.xml" />
        <mapping resource="Log.hbm.xml" />
        <mapping resource="LogXML.hbm.xml" />
        <mapping resource="Messages.hbm.xml" />
        <mapping resource="USER_READ.hbm.xml" />
        <mapping resource="WHO_READ_USER.hbm.xml" />
    </session-factory>
</hibernate-configuration>


Все методы из HibernateSpitterDao вызываются в SpitterServiceImpl.java

@Service("Bean")
@Transactional
public class SpitterServiceImpl implements SpitterService{

    HibernateSpitterDao hibernateSpitterDao;
    HibernateUserReadDao hibernateUserReadDao;
    HibernateWhoReadUserDao hibernateWhoReadUserDao;
    HibernateTopicDao hibernateTopicDao;

    @Autowired
    public void setHibernateSpitterDao(HibernateSpitterDao hibernateSpitterDao){
        this.hibernateSpitterDao=hibernateSpitterDao;
    }
	.....
	//транзакция тут по умо
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor =
            {ObjectNotFoundException.class,ConstraintViolationException.class})
    public Spitter getSpitter(String username){
        return hibernateSpitterDao.getSpitterByUsername(username);
    }
....
}


1-ое:
У меня в классе SpitterServiceImpl.java есть 4 класса и у каждого есть: private SessionFactory sessionFactory. Может этот SessionFactory надо делать синглетоном?
Вот так:
@javax.inject.Singleton
private SessionFactory sessionFactory;

Или подругому как-то?
2-ое:
в методе currentSession() надо возвращать return sessionFactory.openSession() или getCurrentSession()???
private Session currentSession() {
        return sessionFactory.getCurrentSession();
    }

3-ее:
если все нормально, то може надо изоляцию транзакции другую? Не REQUIRED.
В консоли hibernate пишет:

transaction = [email protected]cff9ff
Hibernate: select spitter0_.ID as ID1_2_,................

Кунг-фу принцип: не сталкиваться лоб в лоб с внешними силами,а прогнуться под их давлением с тем, чтобы, разогнувшись, стать еще сильнее.
 
 
Сообщения:139
можно глупый вопрос? а с каких пор необходима инициация транзакции для выборки объектов? и что ты там, собственно, комитишь?

 
 
Сообщения:110
Убрал транзакцию и добавил следущее:

public Spitter getSpitterByUsername(String usernamea) {
        List<Spitter> tempListSpitter = new ArrayList<>(1);
        Spitter spitter;
        try {
            session =   currentSession();
            try {
                String id = session.createQuery(
                        "SELECT id from Spitter WHERE username = ? ").setString(0,usernamea).uniqueResult().toString();
                System.out.println("session===" + session.toString());
                Long id_long = 0L;
                try {
                    id_long = Long.parseLong(id);
                } catch (NumberFormatException e) {
                    System.err.println("Неверный формат строки!");
                }
                System.out.println("id = " + id);
                spitter = (Spitter) session.get(Spitter.class, id_long);

            } catch (HibernateException ex) {
                System.out.println("Spitter = " + ex.toString());
                throw ex;
            }
        } finally {
            //HibernateUtil.closeSession();
        }
        return spitter;
    }


В консоли вывело:
Spitter = org.hibernate.HibernateException: createQuery is not valid without active transaction

Кунг-фу принцип: не сталкиваться лоб в лоб с внешними силами,а прогнуться под их давлением с тем, чтобы, разогнувшись, стать еще сильнее.
 
 
Сообщения:153
Комментарий по поводу первого поста: у Вас аннотация @Transactional установлена над сервисным классом. Поэтому нет смысла в коде DAO начинать новую (программным путём).
Обратите внимание, что у аннотации @Transactional поле "readOnly" по умолчанию имеет значение "false". Также не вижу смысла в описании атрибута "rollbackFor" в аннотации над методом, который работает только на чтение.
На некоторые другие вопросы можете найти ответы вот в этой статье.
 
 
Сообщения:110
Вообщем ошибка была в том что в БД были null значения которые были отмапены на int поля.(что не допустимо) Выход либо использовать в Модели вместо int, Integer или в БД запретить null

Кунг-фу принцип: не сталкиваться лоб в лоб с внешними силами,а прогнуться под их давлением с тем, чтобы, разогнувшись, стать еще сильнее.
 
 
Сообщения:110
wind:
можно глупый вопрос? а с каких пор необходима инициация транзакции для выборки объектов? и что ты там, собственно, комитишь?

createQuery() без транзакции нереал.
А выборка объектов (в моем случае) не на id основана.

Кунг-фу принцип: не сталкиваться лоб в лоб с внешними силами,а прогнуться под их давлением с тем, чтобы, разогнувшись, стать еще сильнее.
Изменен:31 окт 2016 19:16
 
 
Сообщения:139
V_JP:
createQuery() без транзакции нереал

если сессию получаешь с помощью Session#getCurrentSession, то да, костыль такой

 
 
Сообщения:110
wind:
V_JP:
createQuery() без транзакции нереал

если сессию получаешь с помощью Session#getCurrentSession, то да, костыль такой

а если openSession? Разве не аналог.

Кунг-фу принцип: не сталкиваться лоб в лоб с внешними силами,а прогнуться под их давлением с тем, чтобы, разогнувшись, стать еще сильнее.
 
 
Сообщения:139
V_JP:
а если openSession? Разве не аналог.

Нет.

Когда ты берешь текущую, то ею управляет CurrentSessionContext и тебе не надо её явно флушить, закрывать и т. п. По умолчанию, если есть TransactionManagerLookup, используется JTASessionContext, а он хочет транзакцию. Это написано в javadoc, если что.

Когда ты открываешь сессию сам с помощью openSession, то сам должен ею и рулить, тогда никаких транзакций для чтения не нужно.

 
Модераторы:Нет
Сейчас эту тему просматривают:Нет