2011-12-20 3 views
8

Tengo una clase de datos para hibernación asociada a una tabla; imaginar la Entidad persona así:Hibernar: objeto de datos con un nombre de tabla dinámico por anotaciones

@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 
    ... 

Necesito crear tablas históricas por años de esta tabla: Person2010, Person2011, Person2012 ... ¿Es posible, sin crear nuevos objetos de datos? ¿Tal vez por un parámetro ...? No lo sé.

La clase Entity es la misma, cambiando el nombre de la tabla y el constructor.

Respuesta

18

Otro Arquitectura, más complez pero elegante:

, puede cambiar los nombres de las tablas usando NamingStrategies:

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

Y, cuando quiera usar las tablas _year, debe crear una sesión con Hibernate que anule los nombres de las tablas:

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

Para mi arquitectura, creo una sesión por año y la almaceno en el mapa de la aplicación para acceder cuando la necesito.

Gracias.

3

Debe intentar Hibernate Envers para datos históricos.

+0

Gracias a usted. Voy a estudiarlo para mi aplicación. Si resuelve mi problema, estableceré su respuesta como correcta :) – ganzux

+0

Envers es fácil y tal vez la solución pero ... ¿Cómo puedo establecer el sufijo de la tabla Audited de forma dinámica? Necesito separar los datos por años porque tengo millones de datos por tabla y necesito buscar. Gracias – ganzux

+0

¿Por qué no puedes simplemente buscar en una sola tabla? Un buen DBMS debería ser capaz de manejar esto. – tobiasbayer

1

En Hibernate, asigna 1 clase a 1 tabla. No puede reutilizar la misma entidad para asignar varias tablas dinámicamente.

Hibernate Envers es una solución bastante buena para los datos históricos, pero aún no podrá hacer lo que intenta (aumentar dinámicamente el número de tablas sin tocar las entidades del asignador).

+0

Gracias. Voy a estudiarlo para mi aplicación. Si resuelve mi problema, estableceré su respuesta como correcta :) – ganzux

+0

Envers es fácil y quizás la solución, pero ... ¿Cómo puedo establecer el sufijo de la tabla Audited de forma dinámica? Necesito separar los datos por años porque tengo millones de datos por tabla y necesito buscar. Gracias – ganzux

+0

No puedes. ORMs no le ofrece ese nivel de flexibilidad, si realmente desea ir con ese ** mal ** diseño que usted propone, entonces tendrá que renunciar a Hibernate y Envers y usar SQL directo. – edutesoy

1

Gracias a @CodeBrickie y @edutesoy encontré Envers.

Configuro el archivo de configuración de hibernación con el sufijo AUD y creo nuevos archivos de configuración de hibernación por año (hibernate.cfg.2009.xml, hibernate.cfg.2010.xml, hibernate.cfg.2011.xml ...) con el sufijo del año.

Cuando guardo datos, siempre se audita en la tabla AUD. El 1 de enero, automáticamente:

  • _AUD TABLE se renombra como tabla _PAST_YEAR.
  • Se ha creado una nueva tabla _AUD.
  • Se crea un nuevo hibernate.cfg.past_year.xml con el nuevo sufijo.

Cuando necesito obtener datos, cargo el archivo de configuración de hibernación correspondiente.

Espero que esto ayude a los demás :)

1
@Table(name="emd_employee_1001") 

En el nombre del archivo de anotación anterior se puede pasar como parámetro, por ejemplo

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

Sí, está bien, pero una vez que se inicializa el objeto de datos, no puedo cambiar el nombre. – ganzux

0

Modificado en tiempo de ejecución (creo que es la mejor manera):

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