unsaved-value
摘抄2:
inverse和cascade都配置的结果:
You need to explicitly delete() the Child.
Parent p = (Parent) session.load(Parent.class, pid);
Child c = (Child) p.getChildren().iterator().next();
p.getChildren().remove(c);
session.delete(c);
session.flush();
In our case, a Child cannot exist without its parent. So if we remove a Child from the collection, we do want it to be deleted. To do this, we must use cascade="all-delete-orphan".
<set name="children" inverse="true" cascade="all-delete-orphan">
<key column="parent_id"/>
<one-to-many class="Child"/>
</set>
Even though the collection mapping specifies
inverse="true"
,
cascades
are still processed by iterating the collection elements. If you need an object be saved, deleted or updated by cascade, you must add it to the collection. It is not enough to simply call setParent().
|
mappedBy
element and set the many-to-one @JoinColumn
as
insertable and updatable
to false. This solution is obviously
not optimized
and will produce some
additional UPDATE statements(更新外键)
.
class teacher {
List<student> studentList
}
|
class Student{
Teacher teacher
}
|
映射一,单方维护:
class Teacher {
List<student> studentList
}
缺点修改了studentList,需要
手工
Student.
setTeacher
. hibernate的一个缺点,坑.
普通改进:
teacher中;
增加
public void addStudent(
Student staudent
){
student.setTeacher(this);
studentList.add(student)
}
public void addStudentAll( )
最终改进:
双方都维护
注解, 一方增加 @joinColumn ,保持和多端一致
xml , 已经有column一项. inverse=true; 默认是false, 都维护更新
|
class Student{
Teacher teacher
}
|
映射二:
class Teacher {
List<student> studentList
}
|
class Student{
数据库有 teacher外键,但是实体上无 ManyToOne
}
|
Execute all SQL and second-level cache updates, in a special order so that foreign-key constraints cannot be violated:
|
内有重要调用的函数
public Class
CollectionUpdateAction
{
public
void
execute
()
throws
HibernateException {
persister.deleteRows( collection, id, session )
persister.updateRows( collection, id, session );
persister.insertRows( collection, id, session ); // 遍历collection item 判断是否需要生成 prepareStatment,插入id=?的参数值. 注意即使多个item符合,也不会智能生成多个 in( ? ? ? .),还是多个update prepareStatment sql语句.} |
赋值"?"参数值具体堆栈:
关于
prepareStatement的准备, 和执行到数据库引擎.(真正生成mysql的sql日志,binlog)
*对entity类型的使用,
*对参数值的设定.类型转换
*
AbstractCollectionPersister
对list的变动,更新几个bean的决策
BigIntTypeDescriptor$1.doBind(PreparedStatement, X, int, WrapperOptions) line: 52
BigIntTypeDescriptor$1(BasicBinder<J>).bind(PreparedStatement, J, int, WrapperOptions) line: 91
LongType(AbstractStandardBasicType<T>).nullSafeSet(PreparedStatement, Object, int, WrapperOptions) line: 283
LongType(AbstractStandardBasicType<T>).nullSafeSet(PreparedStatement, Object, int, SessionImplementor) line: 278
OneToManyPersister(AbstractCollectionPersister).
writeKey(PreparedStatement, Serializable, int, SessionImplementor) line: 806
这个就是把生成的PreparedStatement,赋值参数. 之前已经打印了固定xx=?的sql.
OneToManyPersister(AbstractCollectionPersister).remove(Serializable, SessionImplementor) line: 1106
CollectionRemoveAction.execute() line: 107
ActionQueue.execute(Executable) line: 273
ActionQueue.executeActions(List) line: 265
ActionQueue.
executeActions() line: 186
DefaultFlushEventListener(AbstractFlushingEventListener).
performExecutions(EventSource) line: 321
{
performExecutions
分成 prepareAction()和
executeAction()
两部分
}
DefaultFlushEventListener.onFlush(FlushEvent) line: 51
SessionImpl.flush() line: 1216
|
获取孤值堆栈代码
AbstractPersistentCollection.getOrphans(Collection, Collection, String, SessionImplementor) line: 901
PersistentSet.getOrphans(Serializable, String) line: 113
CollectionEntry.getOrphans(String, PersistentCollection) line: 373
Cascade.deleteOrphans(String, PersistentCollection) line: 471
Cascade.cascadeCollectionElements(Object, Object, CollectionType, CascadeStyle, Type, Object, boolean) line: 455
Cascade.cascadeCollection(Object, Object, CascadeStyle, Object, CollectionType) line: 362
Cascade.cascadeAssociation(Object, Object, Type, CascadeStyle, Object, boolean) line: 338
Cascade.cascadeProperty(Object, Object, Type, CascadeStyle, String, Object, boolean) line: 204
Cascade.cascade(EntityPersister, Object, Object) line: 161
DefaultAutoFlushEventListener(AbstractFlushingEventListener).cascadeOnFlush(EventSource, EntityPersister, Object, Object) line: 154
DefaultAutoFlushEventListener(AbstractFlushingEventListener).prepareEntityFlushes(EventSource) line: 145
DefaultAutoFlushEventListener(AbstractFlushingEventListener).flushEverythingToExecutions(FlushEvent) line: 88
DefaultAutoFlushEventListener.onAutoFlush(AutoFlushEvent) line: 58
SessionImpl.autoFlushIfRequired(Set) line: 1185 |
||||
拦截器的onDelete堆栈,真正的增加Action在同一函数的(
DefaultDeleteEventListener.deleteEntity(EventSource, Object, EntityEntry, boolean, EntityPersister, Set) line: 275 )
ReplaceableInterceptor.onDelete(Object, Serializable, Object[], String[], Type[]) line: 48
DefaultDeleteEventListener.deleteEntity(EventSource, Object, EntityEntry, boolean, EntityPersister, Set) line: 255
DefaultDeleteEventListener.onDelete(DeleteEvent, Set) line: 162
SessionImpl.fireDelete(DeleteEvent, Set) line: 965
SessionImpl.delete(String, Object, boolean, Set) line: 948
Cascade.deleteOrphans(String, PersistentCollection) line: 486
Cascade.cascadeCollectionElements(Object, Object, CollectionType, CascadeStyle, Type, Object, boolean) line: 455
Cascade.cascadeCollection(Object, Object, CascadeStyle, Object, CollectionType) line: 362
Cascade.cascadeAssociation(Object, Object, Type, CascadeStyle, Object, boolean) line: 338
Cascade.cascadeProperty(Object, Object, Type, CascadeStyle, String, Object, boolean) line: 204
Cascade.cascade(EntityPersister, Object, Object) line: 161
DefaultFlushEventListener(AbstractFlushingEventListener).cascadeOnFlush(EventSource, EntityPersister, Object, Object) line: 154
DefaultFlushEventListener(AbstractFlushingEventListener).prepareEntityFlushes(EventSource) line: 145
DefaultFlushEventListener(AbstractFlushingEventListener).flushEverythingToExecutions(FlushEvent) line: 88
DefaultFlushEventListener.onFlush(FlushEvent) line: 50
SessionImpl.flush() line: 1216
|
||||