使用 Java EE 和 Hibernate 的具有多个项目的 Web 应用程序
我有一个一般性的设计问题困扰了我一段时间。
目标:
- 使用 Vaadin 为前端创建 Web 应用程序
- 用户必须能够在运行时创建项目。每个项目使用相同的(域)模型,但数据不同
- 每个项目的数据必须分开(放入不同的数据库)
- 用户可以登录,选择项目并访问特定的数据库
- 不同的用户可以同时处理不同的项目
- 应用程序使用带有注释和编程配置的 Hibernate
当前情况
- 在许多地方使用静态 HibernateUtil (getSessionFactory.getCurrentSession)
- 使用 ThreadLocal 部分实现 Session-Per-View 模式来获取当前应用程序实例,它作为会话(和事务)管理器,通过使用 HTTPServletRequestListener 在视图请求
- 逻辑层之前和之后打开和关闭会话和事务,而无需直接访问视图层:
- 在某些部分,当前会话是通过使用静态 HibernateUtil 获取的
- 在其他地方,通过构造函数设置会话管理器。然后,该会话管理器被传递到 DAO,为数据检索和操作提供会话
- 创建项目时,使用 Hibernates 创建选项来创建数据库(将来可以在创建时切换为静态 ddl 导入)
问题
可想而知,存在各种各样的问题:
- 静态访问sessionfactory来获取session不能用于多个项目,因为静态HibernateUtil只能同时携带一个(db)url,因此session会混合
- 访问逻辑层的 SessionManager 不太好(需要通过多个构造函数提供它)
- 不同方法的混合是丑陋的,但目标是纠正这种
想法
- 实现依赖注入,即使在逻辑层中也能提供正确的 DAOFactory。用 Guice 尝试过,但如果实例不是通过注入器创建的,则会出现空指针异常(请参阅我的其他问题)。因此它不起作用。
我希望我可以在代码中的任何位置注入/使用 DAO Factory 的正确实例(可以访问正确的会话/数据库),而无需例如逻辑层知道加载了哪个当前数据库。所以逻辑层不应该关心会话处理或其他任何事情。我只想从任何地方拨打 xyDAO.find(id) 或类似电话,它会获取正确的数据库。我还认为,如果逻辑深处只有一个类需要它,那么通过构造函数将 SessionManager 传递给多个类并不好。
您将采取什么方法来实现既定目标?
如果有人可以提供帮助,我将非常感激。如果您需要更多信息,请告诉我,我会提供!
I have a general design question that's bothering me for some time now.
Goal:
- Create a web application using Vaadin for the Front End
- User must be able to create projects during runtime. Every project uses the same (Domain) Model, but different data
- Data for every project must be separated (into different databases)
- User can login, select project and get access to the specific Database
- Different user can work on different projects at the same time
- Application uses Hibernate with Annotations and Programmatic Configuration
Current Situation
- Static HibernateUtil use in many places (getSessionFactory.getCurrentSession)
- Partially Implementation of Session-Per-View Pattern with ThreadLocal to get current Application instance, that works as Session-(and Transaction) Manager by using HTTPServletRequestListener to open and close session and transaction before and after view request
- Logic layer with no direct access to View Layer:
- In some parts, Current Session is get by using the static HibernateUtil
- in other places, by setting the Session Manager via the constructor. This session manager then is passed to a DAO to provide session for Data Retrieval an manipulation
- When project is created, Hibernates create option is used to let the database be created (in future this could be switched to static ddl import at creation)
Problems
As one can imagine, there are various problems:
- Static access to sessionfactory to get session cannot work for multiple projects, as static HibernateUtil can only carry one (db)url at the same time and so sessions get mixed
- Access to SessionManager from Logic Layer is not nice (need to provide it through several constructors)
- mixture of different approaches is ugly, but goal is to straighten this
Thoughts
- Implement Dependency injection to provide correct DAOFactory even in Logic Layer. Tried it with Guice, but get Null Pointer Exceptions if Instances are not created via Injector (see my other question). Therefore it does not work.
I wish i could just inject/use the correct Instance of DAO Factory (which has access to the correct session/db) anywhere in the code without e.g. the logic layer knowing which current database is loaded. So the logic layer should not care about session handling or anything. I just want to make a call do xyDAO.find(id) or similar from anywhere and it gets the correct database. I also think that its not nice to pass the SessionManager through several classes by constructor, if only one class deep down in the logic needs it.
What approach would you take to meet the goals stated?
I would really appreciate if someone could help. If you need additional info, please let me know and I will provide!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您是否对需求和解决方案感到困惑?
真的要求您拥有不同的数据库,还是只是每个项目的数据必须分离?
如果不同的数据库不是绝对要求,只需将
user_id
列添加到足够的表中,这样您就可以为所有用户使用相同的表,但仍能满足此要求。您可以将此方法称为“垂直”数据分区,而不是“水平”分区。
好处应该是显而易见的:突然间你的解决方案变得简单了很多,这是一件好事。
Have you have confused requirements and solutions?
Is there really requirement that you have different databases, or is it just that Data for every project must be separated?
If different databases are not an absolute requirement, just add a
user_id
column to enough tables so you can use the same tables for all users but still achieve this requirement.You could call this approach partitioning the data vertically, rather than horizontally.
The benefit should be immediately obvious: Suddenly your solution is a lot simpler, which is a good thing.