Вопрос по jpa, java, generics – JPA и дженерики

9

Мне интересно, как абстрактный класс с обобщениями будет работать с JPA? Я имею в виду, какие аннотации мне нужны для поля?

Рассмотрим это:

@MappedSuperclass
public abstract class AbstractMyClass<T> {
  // What about Strings and Integers? Do I need some kind of @LOB?
  private T field;

  public T getField() {
    return field;
  }

  public void setField(T field) {
    this.field = field;
  }
}

А потом эти

@Entity
@Table(name = "String")
public class MyStringClass extends AbstractMyClass<String> {
}

@Entity
@Table(name = "Integer")
public class MyIntegerClass extends AbstractMyClass<Integer> {
}
Какую реализацию вы используете? JMelnik
Ну, я попробовал с String и Integer. Он отлично работает, пока вы можете хранить String в varchar2, но я не нашел простого способа аннотировать эту конкретную строку как lob без пользовательских типов. jaakko
Ну ничего особенного. Просто заинтересовался, когда я подумал о будущем ... Я абсолютный новичок, когда дело доходит до ORM, и мне было интересно, могут ли они и как они решают эту проблему. jaakko
Hibernate 3.6 с Oracle 10g в качестве базы данных. Кроме того, я создаю таблицы вручную. jaakko
Чего вы пытаетесь достичь на уровне дизайна? Какой смысл иметь такой суперкласс? Istvan Devai

Ваш Ответ

2   ответа
6

потому что универсальный тип отображается на уровне абстрактного класса, а для ваших конкретных классов он имеет ровно одно значение на класс. Фактически, JPA будет хранить ваши подклассы в одной или нескольких таблицах в соответствии с выбранной вами @InheritanceStrategy и использует для этого другой механизм.

Вы можете сами понять, почему ваш случай не является проблемой, рассуждая о том, как ORM может сохранить два класса в БД:

You can store MyStringClass and MyIntegerClass in the same table, adding a Discriminator column so that the ORM, when it loads from the DB, know which constructor should be called. You can store every subclass in more table.

С другой стороны, невозможно определить общий

@Entity
@Table(name = "MyGenericClass")
public class MyGenericClass<T> {
    private T t;
    public MyGenericClass(T t) {
       this.t=t;
    }
}

Причина этого заключается в том, что во время компиляции T стирается. из-за стирания типа. Он используется во время компиляции для проверки подписей и правильности типов, но затем он превращается в java.lang.Object внутри JVM. Если вы будете следовать до сих пор, вы должны понимать следующее:

In your case, every concrete subclass of AbstractMyClass has a type T which is defined for all instances of the class. While the T information is not retained into the AbstractMyClass, it is retained and unique inside the subclasses. In the second case I posted, each possible concrete instance of MyGenericClass could have a possible different value for T, and because of type erasure this information is not retained.

* Примечание: тот факт, что второй случай не может быть обработан JPA, является абсолютно разумным, и если вы попадаете в этот случай, вы должны задать себе вопросы о своем дизайне. Обобщения являются отличным инструментом для разработки гибких классов, которые могут обрабатывать другие классы безопасным для типов образом, но типобезопасный - это концепция языка программирования, которая не имеет ничего общего с постоянством.

Дополнительно: вы можете использовать javap, чтобы увидеть, что на самом деле стирает. Снимите аннотации с MyGenericClass и скомпилируйте его.

G:\>javac MyGenericClass.java

G:\>javap -p MyGenericClass
Compiled from "MyGenericClass.java"
public class MyGenericClass extends java.lang.Object{
    private java.lang.Object t;
    public MyGenericClass(java.lang.Object);
}
Я попробовал это, и он выдал исключение @Entity @Table (name = & quot; MyFoo & quot;). Открытый класс MyFooClass extends AbstractMyClass & lt; Foo & gt; {} Причина: org.hibernate.MappingException: Не удалось определить тип для: fukoka.foobar.Foo, для таблицы: MyFoo, для столбцов: [org.hibernate.mapping.Column (field)]
-2

T инвентарьSerializable

@Entity
public class IgsSubject extends BasicObject implements Serializable{

    private static final long serialVersionUID = -5387429446192609471L;

@MappedSuperclass
public class IgsBasicLog<T> extends BasicObject {

    @ManyToOne
    @JoinColumn(name = "ITEM_ID")
    private T item;

@Entity
public class IgsLogA extends IgsBasicLog<IgsSubject> implements Serializable {
    private static final long serialVersionUID = -8207430344929724212L;
}
Объясните пожалуйста почемуT необходимо реализоватьSeralizable так как имо нужно расширять тип сущности.
больше кода объяснить ...

Похожие вопросы