【问题标题】:Hibernate: Data Object with a dynamic table name by AnnotationsHibernate:通过注释具有动态表名的数据对象
【发布时间】:2012-01-24 07:11:35
【问题描述】:

我有一个与表关联的 Hibernate 数据类;想象像这样的实体Person

 @Entity
 @org.hibernate.annotations.Proxy(lazy=false)
 @Table(name="Person", schema="MySchema")
 @Inheritance(strategy=InheritanceType.SINGLE_TABLE)
 public class ProfileData implements Serializable {

    private static final long serialVersionUID = -844564646821609090L;

    public PersonData() {
    }

    @Column(name="idPerson", nullable=false, unique=true)   
    @Id 
    ...

我需要按此表的年份创建历史表:Person2010、Person2011、Person2012... 是否可以不创建新的数据对象?也许通过参数...?我不知道。

Entity类是一样的,只是改变了表名和构造函数。

【问题讨论】:

    标签: java hibernate annotations


    【解决方案1】:

    另一种架构,更复杂但优雅:

    YES,您可以使用 NamingStrategies 更改表名:

    public class MyNamingStrategy extends DefaultNamingStrategy {
       ...
       @Override
       public  String tableName(String tableName) {
          return tableName+yearSuffixTable;
       }
       ...
    }
    

    而且,当您想使用 _year 表时,您必须使用 Hibernate 创建一个覆盖 rhe 表名称的会话:

      SessionFactory sessionFactory;
      Configuration config = new AnnotationConfiguration()
                             .configure("hibernate.cfg.xml")
                             .setNamingStrategy( new MyNamingStrategy () );
      sessionFactory = config.buildSessionFactory();
      session = sessionFactory.openSession();
    

    对于我的架构,我按年创建一个会话并将其存储到应用程序映射中,以便在需要时访问。

    谢谢。

    【讨论】:

      【解决方案2】:

      您应该尝试Hibernate Envers 获取历史数据。

      【讨论】:

      • 谢谢。我将为我的应用程序研究它。如果它解决了我的问题,我会将您的答案设置为正确:)
      • Envers 很简单,也许是解决方案,但是...如何动态设置 Audited 表后缀?我需要按年分隔数据,因为每个表有数百万个数据,我需要继续搜索。谢谢
      • 为什么不能只搜索一张表?一个好的 DBMS 应该能够处理这个问题。
      • 我不能。我需要按年份存储在表中的数据。它更有效率。我将尝试使用不同的休眠配置逐年创建一个会话...
      • 你为什么这么肯定分开表更有效?
      【解决方案3】:

      在 Hibernate 中,您将 1 个类映射到 1 个表。您不能重复使用同一个实体来动态映射多个表。

      Hibernate Envers 是一个很好的历史数据解决方案,但你仍然无法做你尝试的事情(在不触及映射器实体的情况下动态增加表的数量)。

      【讨论】:

      • 谢谢。我将为我的应用程序研究它。如果它解决了我的问题,我会将您的答案设置为正确:)
      • Envers 很简单,也许是解决方案,但是...如何动态设置 Audited 表后缀?我需要按年分隔数据,因为每个表有数百万条数据,我需要继续搜索。谢谢
      • 你不能。 ORM 无法为您提供那种级别的灵活性,如果您真的想采用您提出的那种糟糕设计,那么您将不得不放弃 Hibernate 和 Envers 并使用直接 SQL。
      • 嗯,不了解整个设计的糟糕设计有点自大。而且我可以根据我选择的年份做我需要加载的休眠配置文件。
      【解决方案4】:

      感谢@CodeBrickie 和@edutesoy,我找到了 Envers。

      我使用 AUD 后缀配置休眠配置文件,并每年创建新的休眠配置文件(hibernate.cfg.2009.xml、hibernate.cfg.2010.xml、hibernate.cfg.2011.xml...)年份后缀。

      当我保存数据时,总是在 AUD 表中进行审计。 1 月 1 日,自动:

      • _AUD TABLE 被重命名为 _PAST_YEAR 表。
      • 创建了一个新的 _AUD 表。
      • 使用新后缀创建新的 hibernate.cfg.past_year.xml。

      当我需要获取数据时,我会加载对应的hibernate配置文件。

      希望这对其他人有帮助:)

      【讨论】:

        【解决方案5】:
        @Table(name="emd_employee_1001")
        

        上面的注解文件名可以作为参数传递,例如

        x=1001 
        @Table(name="emd_employee_+x+")
        

        【讨论】:

        • 是的,好的,但是一旦初始化数据对象,我就不能更改名称了。
        【解决方案6】:

        在运行时修改(我认为这是最好的方式):

        Session session = super.getSession();
            SQLQuery query = session.createSQLQuery("raw sql");
            query.setParameter(":abc", "value");
            query.addEntity(Some.class);
            return query.list();
        

        【讨论】:

        • 这是一个 SQL 查询。这不适用于多个 DB(Oracle DB、Microsoft SQL Server、Sybase)。编写不能在多个数据库上运行的 SQL 代码非常容易。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-07-23
        • 2022-11-28
        • 1970-01-01
        • 1970-01-01
        • 2015-11-12
        • 2021-01-04
        • 1970-01-01
        相关资源
        最近更新 更多