создать идеальный сущностей jpa




я работаю с спд (реализации hibernate) в течение некоторого времени теперь, и каждый раз, когда мне нужно создать сущности я считаю себя борется с проблемами как для параметра accesstype, неизменяемые свойства, равен/хэш-код, ... .поэтому я решил попробовать и найти общие рекомендации для каждого вопроса и запишите это для личного пользования.я не против чтобы кто-нибудь прокомментировать или сказать мне, где я ошибаюсь.

класс сущностей

  • implement serializable

    reason: the specification says you have to, but some jpa providers do not enforce this. hibernate as jpa provider does not enforce this, but it can fail somewhere deep in its stomach with classcastexception, if serializable has not been implemented.

  • конструкторы

  • create a constructor with all required fields of the entity

    reason: a constructor should always leave the instance created in a sane state.

  • besides this constructor: have a package private default constructor

    reason: default constructor is required to have hibernate initialize the entity; private is allowed but package private (or public) visibility is required for runtime proxy generation and efficient data retrieval without bytecode instrumentation.

  • поля/свойства

  • use field access in general and property access when needed

    reason: this is probably the most debatable issue since there are no clear and convincing arguments for one or the other (property access vs field access); however, field access seems to be general favourite because of clearer code, better encapsulation and no need to create setters for immutable fields

  • omit setters for immutable fields (not required for access type field)

  • properties may be private
    reason: i once heard that protected is better for (hibernate) performance but all i can find on the web is: hibernate can access public, private, and protected accessor methods, as well as public, private and protected fields directly. the choice is up to you and you can match it to fit your application design.
  • равен/хэш-код

  • never use a generated id if this id is only set when persisting the entity
  • by preference: use immutable values to form a unique business key and use this to test equality
  • if a unique business key is not available use a non-transient uuid which is created when the entity is initialised; see this great article for more information.
  • never refer to related entities (manytoone); if this entity (like a parent entity) needs to be part of the business key then compare the id's only. calling getid() on a proxy will not trigger the loading of the entity, as long as you're using property access type.
  • пример сущности

    @entity@table(name = "room")public class room implements serializable {    private static final long serialversionuid = 1l;    @id    @generatedvalue    @column(name = "room_id")    private integer id;    @column(name = "number")     private string number; //immutable    @column(name = "capacity")    private integer capacity;    @manytoone(fetch = fetchtype.lazy, optional = false)    @joincolumn(name = "building_id")    private building building; //immutable    room() {        // default constructor    }    public room(building building, string number) {        // constructor with required field        notnull(building, "method called with null parameter (application)");        notnull(number, "method called with null parameter (name)");        this.building = building;        this.number = number;    }    @override    public boolean equals(final object otherobj) {        if ((otherobj == null) || !(otherobj instanceof room)) {            return false;        }        // a room can be uniquely identified by it's number and the building it belongs to; normally i would use a uuid in any case but this is just to illustrate the usage of getid()        final room other = (room) otherobj;        return new equalsbuilder().append(getnumber(), other.getnumber())                .append(getbuilding().getid(), other.getbuilding().getid())                .isequals();        //this assumes that building.id is annotated with @access(value = accesstype.property)     }    public building getbuilding() {        return building;    }    public integer getid() {        return id;    }    public string getnumber() {        return number;    }    @override    public int hashcode() {        return new hashcodebuilder().append(getnumber()).append(getbuilding().getid()).tohashcode();    }    public void setcapacity(integer capacity) {        this.capacity = capacity;    }    //no setters for number, building nor id}

    другие предложения, чтобы добавить в этот список более чем приветствуется...

    updatethis article

    после прочтения я адаптировал свой способ реализации экв/нс:

  • if an immutable simple business key is available: use that
  • in all other cases: use a uuid