2014-01-28 2 views
0

Я хочу изменить уникальный ключ от одного объекта объекта к другому в одном @Transaction метод:Hibernate и флеш: обновление бросает дубликат ключа ошибки

Entity oldone=dao.getEntity(oldid); 
Entity newone=dao.getEntity(newid); 
oldone.setBarcode(null); 
dao.update(oldone); //free the unique key "barcode" 
newone.setBarcode(barcode); 
dao.update(newone); //set the unique key "barcode" 

Но этот код бросает: Дублировать запись для ключа «штрих-код» Дубление Я обнаружил, что после первого dao.update в базе данных ничего не меняется. I судимый установить спящий режим flushmode на «всегда», но не изменился:

<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> 
    <property name="hibernateProperties"> 
     <props> 
      <prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop> 
      <prop key="hibernate.show_sql">false</prop>    
      <prop key="hibernate.bytecode.use_reflection_optimizer">false</prop> 
      <prop key="hibernate.cglib.use_reflection_optimizer">true</prop> 
      <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> 
      <prop key="hibernate.search.autoregister_listeners">false</prop> 
      <prop key="hibernate.transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</prop> 
      <prop key="hibernate.flushMode">always</prop> 
     </props> 
    </property> 
</bean> 

Почему спящий режим не смывать?

+0

Похоже, что всегда полностью игнорируется, потому что, если после обновления вы добавите «session.flush()», все будет работать. – Tobia

+0

Почему вы пишете эту собственность два раза? false Krishna

+0

Только CTRL-C CTRL-V ошибка. – Tobia

ответ

1

Похоже, что это свойство Hibernate является лишь намеком на Hibernate. См here и в Hibernate ORM Docs, где они говорят

исключением случаев, когда вы явно Flush(), нет абсолютно никаких гарантий о том, когда сессия выполняет JDBC звонки, только порядок в которых они выполняются.

Больше к этому, FlushMode.ALWAYS enum value Javadoc утверждает, что

Сессия смывается перед каждым запросом. Это почти всегда не нужно и неэффективно.

Я не уверен, что по запросу запрос подразумевает только запрос на базу данных (чтение) или любую операцию, включая вставки, обновления и удаления.

Если бы я был вами, я бы сразу разместил вызов session.flush() после первого обновления. Я знаю, что декларативный способ более чист, но иногда императивное программирование делает ваш бизнес более безопасным.

+0

Я сделаю выбор между АВТО (я не знаю, что он делает) и ВСЕГДА (абсолютно без гарантий того, когда его покраснели) ... замечательно. – Tobia

0

Заставьте эту сессию заподлицо. Должен быть вызван в конце единицы работы, прежде чем совершить транзакцию и закрыть сеанс (в зависимости от режима флеша Transaction.commit() вызывает этот метод).

При создании новых объектов постоянно сохраняйте флеш(), а затем очищайте() сессию регулярно, чтобы контролировать размер кеша первого уровня.

Batch Processing

Session session = sessionFactory.openSession(); 
Transaction tx = session.beginTransaction(); 

for (int i=0; i<100000; i++) { 
    Customer customer = new Customer(.....); 
    session.save(customer); 
    if (i % 20 == 0) { //20, same as the JDBC batch size 
     //flush a batch of inserts and release memory: 
     session.flush(); 
     session.clear(); 
    } 
} 

tx.commit(); 
session.close(); 

Look this.

Она утверждает, что когда Tx.commit(); происходит, тогда вызывается функция Flush. Нет необходимости даже писать эту функцию.

+0

Я до сих пор не понимаю hibernate.flushMode = always property – Tobia

+0

Если режим флеша «AUTO» перед запуском любого спящего режима запроса, проверьте, есть ли какие-либо таблицы для обновления. Если да, то флеш будет выполнен иначе. Если режим флеша - «ВСЕГДА», то сброс произойдет, даже если нет таблиц, которые необходимо обновить. – Krishna

+0

Кажется, это теория, но не то, что она действительно делает. – Tobia

Смежные вопросы