问题:
我在两个实体A和B 之间有多对多的关联.我将一个实体设置为他们关系的所有者(inverse = true在b.hbm.xml中的A集合中).
当我删除A实体时,删除连接表中的相应记录.
当我删除B实体时,不删除连接表中的相应记录(完整性违规例外).
-
让我们考虑一些非常简单的例子:
class A{
Set<B> bset=new HashSet<B>();
//...
}
class B{
Set<A> aset=new HashSet<A>();
//...
}
Run Code Online (Sandbox Code Playgroud)
文件a.hbm.xml [m-to-m mappings only]:
<set name="bset" table="AB">
<key name="a_id"/>
<many-to-many column="b_id" class="B"/>
</set>
Run Code Online (Sandbox Code Playgroud)
文件b.hbm.xml [m-to-m mappings only]:
<set name="aset" table="AB" inverse="true">
<key name="b_id"/>
<many-to-many column="a_id" class="A"/>
</set> …
Run Code Online (Sandbox Code Playgroud) 我只是不明白为什么Hibernate抛出标题中提到的异常.我可能不了解Hibernate背后的状态管理理念.
我有以下情况:
组织与员工之间的一对多关系
Organization.hmb.xml
<set name="employees" inverse="true" cascade="save-update">
<key column="organization_id"/>
<one-to-many class="Employee"/>
</set>
Run Code Online (Sandbox Code Playgroud)
Employee.hbm.xml
<many-to-one name="organization" class="Organization" column="organization_id" />
Run Code Online (Sandbox Code Playgroud)
我使用标准的Spring/Hibernate应用程序架构与服务和DAO,其中DAO扩展HibernateDaoSupport类并使用HibernateTemplate类的服务进行会话管理.
当我尝试在此场景中删除Employee时...
Employee e=employeeService.read(1);
//EDIT: Important! delete operation in EmployeeService is (@)transactional
employeeService.delete(e); //this call just delegate execution to employeeDao.delete
Run Code Online (Sandbox Code Playgroud)
编辑:我最初没有提到服务层中的删除操作是事务性的,这似乎是重要的信息(继续阅读)!
Hibernate抛出......
ObjectDeletedException: deleted object would be re-saved by cascade...
Run Code Online (Sandbox Code Playgroud)
EmployeeService中的删除操作看起来像......
@Transactional public void delete(Employee emp){
Employee e=employeeDao.read(emp.getId());
if(e==null)
throw NoSuchOrganizationException();
/*...several while-s to delete relations where Employee is
not owner of relation... */
employeeDao.delete(e);
}
Run Code Online (Sandbox Code Playgroud)
场景(它们没有关联):
1.当我从Organization.hbm.xml中的关系映射到Employee(s)中 …
我在项目中使用Spring/Hibernate组合,使用标准的CRUD操作.
我想知道,在删除或更新之前验证对象存在是否合理?如果是,哪里是最合适的地方 - 服务还是dao层?
编辑:
对不起,当我问这个问题时,我没有说明问题.存在检查的唯一动机是向服务客户端抛出友好的异常(没有DAO特定).
问题是我必须做'存在检查,因为我的服务方法是事务性的,除此之外,我正在使用HibernateTemplate和DaoSupport助手类在DAO对象中进行会话操作.
根据提到,Hibernate异常(例如在删除不存在的实例的情况下)在提交时抛出,这是我无法实现的,因为(我想)提交是由代理对象中的PlatformTransactionManager执行的,我没有机会在我的服务方法中处理该异常并向客户端重新抛出一些友好的异常.
但是,即使我在删除之前保持我的策略检查存在,但是在实例存在的情况下,我遇到了NonUniqueObjectException问题,因为我重新附加(在删除时间内)已经加载的实例(在读取时间内存在)检查).
例如:
//Existence checking in this example is not so important
public void delete(Employee emp){
Employee tempEmp=employeeDao.read(emp.getId());
if(tempEmp==null)
throw new SomeAppSpecificException();
}
//Existence checking in this example is maybe 'more logical'
public void save(Assignment a){
Task t=taskDao.read(a.getTask().getId());
if(t==null)
throw new FriendlyForeignKeyConstraintException();
Employee e=employeeDao.read(a.getEmployee().getId());
if(e==null)
throw new EmployeeNotFoundExc();
//...some more integrity checking and similar...
assignmentDao.save(a);
}
Run Code Online (Sandbox Code Playgroud)
关键是我只想在上述情况(完整性违规和类似情况)中使用适当的消息抛出友好异常.
我遇到了这篇文章标题中提到的问题。默认情况下,复合模式具有复合 -> 组件关联的显式实现。但我还需要实现相反方向的关联:组件 -> 复合。
简而言之,复合模式中组件和复合对象之间双向关联的最佳解决方案是什么?
我知道这是一个简单的问题,但我有些困惑.
如果我理解得很好,简单来说,当请求到达Web服务器时,他会为每个请求创建一个线程给某个servlet.
考虑到我们在MyServlet中有下一个代码(我遗漏了异常处理和类似的代码):
synchronized protected void doGet( ... ...){
PrintWritet pw=response.getWriter();
String param=request.getParameter("p");
if(param.equals("a")){
wait();
}else{
notifyAll();
}
pw.write("Hello!");
}
Run Code Online (Sandbox Code Playgroud)
我希望这个servlet会卡住,因为进入这个方法的第一个线程(带有param = a)将永远等待,因为任何其他未来的线程都会因为synchronized关键字而停留在doGet前面,并且因为那个notifyAll将永远不会得到执行.
现在,如果我在浏览器中打开新选项卡并点击/ MyServlet?p = a,浏览器等待127.0.0.1 ...之后,我打开新标签并点击/ MyServlet?p = b(或任何东西!= a )第一个标签发布并打印出"你好!" 信息.
这意味着第二个线程已进入doGet,并执行notifyAll.
为什么会这样?我错过了什么?
hibernate ×3
composite ×1
dao ×1
java ×1
many-to-many ×1
one-to-many ×1
servlets ×1
spring ×1
synchronized ×1
validation ×1