私は「予約」エンティティを「部分」エンティティと定義しました。それらの関係は1対多です。私の場合、そのような操作がありました
ステップ 1: FK で 1 つの予約を取得します。この予約の下にあると仮定します。3 つの部分があり、UI に表示されます。
ステップ 2: UI で、新しいパーツを 1 つ追加し、元の 3 つの保存済みパーツを削除済みパーツとしてマークし、最後にこの予約を再度保存します。
バックエンドでは、保存ロジックを次のように処理します
まず、予約アクションの保存機能は次のとおりです
public String save() throws Exception{
booking = preSave(booking);
booking = doSave(booking);
booking = postSave(booking);
return SUCCESS;
}
doSave 関数は次のとおりです。
@Transactional(propagation=Propagation.REQUIRED,isolation=Isolation.DEFAULT)
private Booking doSave(Booking booking) throws Exception{
logger.debug("save booking start,will delete to be deleted/update/save record in DB");
//Step 1:Get booking DAO from spring context
BookingDAO dao = (BookingDAO) DAOFactory.getDAO("Booking");
//Step 2:Get the to be deleted object from booking tree,as usual,the to be deleted object is marked in UI
List toBeDeleted = BookingUtil.handleDeletedObj(booking);
logger.debug("The to be deleted object is ["+toBeDeleted+"]");
//Step 3:If to be deleted object is not empty,invoke booking DAO's delete function to delete them
if(toBeDeleted!=null && toBeDeleted.size()>0){
dao.delete(toBeDeleted);
}
//Step 4:Invoke booking DAO's save function to save/update obj
booking = (Booking) dao.save(booking);
return booking;
}
DAOの削除機能
@Override
@Transactional(propagation=Propagation.REQUIRED,isolation=Isolation.DEFAULT)
public Object delete(Object object) {
// TODO Auto-generated method stub
logger.debug("delete to be deleted object ["+object+"]");
if(object == null){
logger.error("there is no to be deleted object found");
return null;
}
Session session = sf.openSession();
if(object instanceof List){
List list = (List) object;
for(Object obj:list){
session.delete(obj);
}
//session.flush();
return list;
}
return object;
}
予約DAOの保存機能
@オーバーライド
@Transactional(propagation=Propagation.REQUIRED,isolation=Isolation.DEFAULT)
public Object save(Object object) {
logger.debug("save() start,save booking["+object+"] to DB");
Booking booking = (Booking)object;
String bookingNo = null;
//Step 1:Check if booking no is empty,if empty,generate booking no by customer first
if(booking.getBookingNo() == null || booking.getBookingNo().trim().isEmpty()){
logger.debug("save(),find booking no is empty,will generate booking no first");
bookingNo = (String) generateBookingNo(booking.getCustomer());
//Set generated booking no to booking
booking.setBookingNo(bookingNo);
}
//Step 2:Set part's FK bookingNo
List <Part>parts = booking.getParts();
if(parts!=null){
for(Part part:parts){
if(part.getBookingNo() == null || part.getBookingNo().isEmpty()){
part.setBookingNo(booking.getBookingNo());
}
}
}
//Step 3:Set todoitem's FK
List<ToDoItem>toDoItems = booking.getToDoItems();
if(toDoItems!=null){
for(ToDoItem toDoItem:toDoItems){
if(toDoItem.getBookingNo() == null || toDoItem.getBookingNo().isEmpty()){
toDoItem.setBookingNo(booking.getBookingNo());
}
}
}
//Step 4:Save/update booking
Session session = sf.getCurrentSession();
session.saveOrUpdate(booking);
session.flush();
return booking;
}
ご覧のとおり、私のロジックは非常に単純です。ものを削除して保存します。この点を除けば、それらは 1 つのトランザクションである必要がありますが、テストを行うと、保存アクションの save() を呼び出した後に部品が削除されていないことがわかりました。まったく、ログは次のとおりです。
17:37:36,143 DEBUG BookingDAO:122 - delete to be deleted object [[com.chailie.booking.model.booking.Part@712e3058, com.chailie.booking.model.booking.Part@f681b75, com.chailie.booking.model.booking.Part@7be2a639]]
17:37:36,144 DEBUG SessionImpl:220 - opened session at timestamp: 13676602561
17:37:36,147 DEBUG DefaultDeleteEventListener:65 - entity was not persistent in delete processing
17:37:36,149 DEBUG VersionValue:44 - version unsaved-value strategy UNDEFINED
17:37:36,150 DEBUG IdentifierValue:104 - id unsaved-value: null
17:37:36,153 DEBUG DefaultDeleteEventListener:180 - deleting [com.chailie.booking.model.booking.Part#2]
17:37:36,154 DEBUG SessionImpl:1308 - setting cache mode to: GET
17:37:36,155 DEBUG SessionImpl:1308 - setting cache mode to: NORMAL
17:37:36,160 DEBUG SessionImpl:1308 - setting cache mode to: GET
17:37:36,162 DEBUG SessionImpl:1308 - setting cache mode to: NORMAL
17:37:36,162 DEBUG DefaultDeleteEventListener:65 - entity was not persistent in delete processing
17:37:36,163 DEBUG VersionValue:44 - version unsaved-value strategy UNDEFINED
17:37:36,163 DEBUG IdentifierValue:104 - id unsaved-value: null
17:37:36,164 DEBUG DefaultDeleteEventListener:180 - deleting [com.chailie.booking.model.booking.Part#3]
17:37:36,165 DEBUG SessionImpl:1308 - setting cache mode to: GET
17:37:36,165 DEBUG SessionImpl:1308 - setting cache mode to: NORMAL
17:37:36,166 DEBUG SessionImpl:1308 - setting cache mode to: GET
17:37:36,166 DEBUG SessionImpl:1308 - setting cache mode to: NORMAL
17:37:36,167 DEBUG DefaultDeleteEventListener:65 - entity was not persistent in delete processing
17:37:36,168 DEBUG VersionValue:44 - version unsaved-value strategy UNDEFINED
17:37:36,168 DEBUG IdentifierValue:104 - id unsaved-value: null
17:37:36,169 DEBUG DefaultDeleteEventListener:180 - deleting [com.chailie.booking.model.booking.Part#4]
17:37:36,170 DEBUG SessionImpl:1308 - setting cache mode to: GET
17:37:36,171 DEBUG SessionImpl:1308 - setting cache mode to: NORMAL
17:37:36,171 DEBUG SessionImpl:1308 - setting cache mode to: GET
17:37:36,172 DEBUG SessionImpl:1308 - setting cache mode to: NORMAL
17:37:36,173 DEBUG JDBCTransaction:103 - commit
17:37:36,174 DEBUG SessionImpl:337 - automatically flushing session
17:37:36,174 DEBUG JDBCContext:201 - before transaction completion
17:37:36,175 DEBUG SessionImpl:393 - before transaction completion
17:37:36,176 DEBUG JDBCTransaction:193 - re-enabling autocommit
17:37:36,177 DEBUG JDBCTransaction:116 - committed JDBC Connection
17:37:36,178 DEBUG JDBCContext:215 - after transaction completion
17:37:36,178 DEBUG ConnectionManager:296 - transaction completed on session with on_close connection release mode; be sure to close the session to release JDBC resources!
17:37:36,179 DEBUG SessionImpl:422 - after transaction completion
17:37:36,179 DEBUG SessionImpl:353 - automatically closing session
17:37:36,180 DEBUG SessionImpl:273 - closing session
17:37:36,180 DEBUG ConnectionManager:374 - performing cleanup
17:37:36,181 DEBUG ConnectionManager:435 - releasing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)]
17:37:36,182 DEBUG JDBCContext:215 - after transaction completion
17:37:36,182 DEBUG ConnectionManager:296 - transaction completed on session with on_close connection release mode; be sure to close the session to release JDBC resources!
17:37:36,183 DEBUG SessionImpl:422 - after transaction completion
17:37:36,184 DEBUG SessionImpl:273 - closing session
しかし、DAO の delete() の予約の最後に session.flush() を追加すると、DB の一部が正常に削除される可能性があります。
私の質問は次のとおりです。DAOのdelete function()にflush()がなかった場合、なぜその部分を削除できないのですか?
Ps:私のセッション ファクトリのスプリング構成は次のとおりです。
bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource1" />
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.MySQLDialect
</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.transaction.flush_before_completion">true</prop>
<prop key="hibernate.transaction.auto_close_session">true</prop>
<prop key="hibernate.connection.release_mode">auto</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="format_sql">true</prop>
</props>
</property>
<property name="packagesToScan">
<list>
<value>com.chailie.booking.model.*</value>
</list>
</property>