как сделать составной первичный ключ (аннотация персистентности Java)

m// оператор имеет некоторые неясные особые случаи:

  • , Если Вы используете ? в качестве разделителя, он только соответствует однажды, если Вы не звоните reset.
  • , Если Вы используете ' в качестве разделителя, шаблон не интерполирован.
  • , Если шаблон пуст, он использует шаблон от последнего успешного соответствия.
18
задан nyxz 9 October 2014 в 16:13
поделиться

4 ответа

У вас уже есть несколько хороших ответов о том, как сделать именно то, что вы просите ..

Для справки позвольте мне просто упомянуть рекомендуемый способ сделать это в Hibernate, который - использовать суррогатный ключ в качестве первичного ключа и отмечать бизнес-ключи как NaturalId:

Хотя мы рекомендуем использовать суррогатные ключи в качестве первичных ключей, вы следует попытаться определить естественные ключи для всех сущностей. Естественный ключ - это собственность или комбинация свойств который уникален и не равен нулю. это также неизменный. Сопоставьте свойства естественный ключ внутри элемент. Hibernate будет сгенерировать необходимый уникальный ключ и ограничения допустимости значений NULL и, как результат, ваше отображение будет больше самодокументируемый.

Рекомендуется реализовать equals () и hashCode () для сравнения естественные ключевые свойства объекта.

В коде, использующем аннотации, это будет выглядеть примерно так:

@Entity
public class UserRole {
  @Id
  @GeneratedValue
  private long id;

  @NaturalId
  private User user;
  @NaturalId
  private Role role;
}

Использование этого избавит вас от многих головных болей в будущем, поскольку вы узнаете, когда вам часто приходится ссылка / сопоставление составного первичного ключа.

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

22
ответ дан 30 November 2019 в 07:18
поделиться

Спасибо, что улучшили свой вопрос ... и приняли во внимание предложения.

(Извините, это немного странно, что вы прикрепляете свои сущности к Даосу, но это не точка.)

Я не уверен, что осталась какая-то проблема:

  • Каждая из двух описываемых вами сущностей имеет один PK, а не пару.
  • В таблице ссылок нет соответствующей сущности, это неявно определяется двумя объектами и их отношением ManyToMany. Если вам нужна третья сущность, измените свой ManyToMany на пару отношений OneToMany и ManyToOne.
1
ответ дан 30 November 2019 в 07:18
поделиться

Составные ключи создаются с использованием @IdClass (другой способ - использовать @EmbeddedId и @Embeddable, не знаю, какой из них вы ищете) @IdClass выглядит следующим образом

@Entity
@IdClass(CategoryPK.class)
public class Category {
    @Id
    protected String name;

    @Id
    protected Date createDate;

}

public class CategoryPK implements Serializable {

    String name;

    Date createDate;

    public boolean equals(object other) {
        //implement a equals that the PP can use to determine 
        //how the CategoryPK object can be identified.
    }

    public int hashCode(){
        return Super.hashCode();
    }
}

моя Категория здесь будет быть вашими user_roles, а имя и createDate будут вашими идентификаторами пользователя и ролью

2
ответ дан 30 November 2019 в 07:18
поделиться

Чтобы выполнить ваше требование, вы можете сопоставить свой @ManyToMany как сопоставление @OneToMany. Таким образом, USER_ROLE будет содержать как USER_ID, так и ROLE_ID в качестве составного первичного ключа

. Я покажу вам, как:

@Entity
@Table(name="USER")
public class User {

    @Id
    @GeneratedValue
    private Integer id;

    @OneToMany(cascade=CascadeType.ALL, mappedBy="joinedUserRoleId.user")
    private List<JoinedUserRole> joinedUserRoleList = new ArrayList<JoinedUserRole>();

    // no-arg required constructor
    public User() {}

    public User(Integer id) {
        this.id = id;
    }

    // addRole sets up bidirectional relationship
    public void addRole(Role role) {
        // Notice a JoinedUserRole object
        JoinedUserRole joinedUserRole = new JoinedUserRole(new JoinedUserRole.JoinedUserRoleId(this, role));

        joinedUserRole.setUser(this);
        joinedUserRole.setRole(role);

        joinedUserRoleList.add(joinedUserRole);
    }

}

@Entity
@Table(name="USER_ROLE")
public class JoinedUserRole {

    public JoinedUserRole() {}

    public JoinedUserRole(JoinedUserRoleId joinedUserRoleId) {
        this.joinedUserRoleId = joinedUserRoleId;
    }

    @ManyToOne
    @JoinColumn(name="USER_ID", insertable=false, updatable=false)
    private User user;

    @ManyToOne
    @JoinColumn(name="ROLE_ID", insertable=false, updatable=false)
    private Role role;

    @EmbeddedId
    // Implemented as static class - see bellow
    private JoinedUserRoleId joinedUserRoleId;

    // required because JoinedUserRole contains composite id
    @Embeddable
    public static class JoinedUserRoleId implements Serializable {

        @ManyToOne
        @JoinColumn(name="USER_ID")
        private User user;

        @ManyToOne
        @JoinColumn(name="ROLE_ID")
        private Role role;

        // required no arg constructor
        public JoinedUserRoleId() {}

        public JoinedUserRoleId(User user, Role role) {
            this.user = user;
            this.role = role;
        }

        public JoinedUserRoleId(Integer userId, Integer roleId) {
            this(new User(userId), new Role(roleId));
        }

        @Override
        public boolean equals(Object instance) {
            if (instance == null)
                return false;

            if (!(instance instanceof JoinedUserRoleId))
                return false;

            final JoinedUserRoleId other = (JoinedUserRoleId) instance;
            if (!(user.getId().equals(other.getUser().getId())))
                return false;

            if (!(role.getId().equals(other.getRole().getId())))
                return false;

            return true;
        }

        @Override
        public int hashCode() {
            int hash = 7;
            hash = 47 * hash + (this.user != null ? this.user.hashCode() : 0);
            hash = 47 * hash + (this.role != null ? this.role.hashCode() : 0);
            return hash;
        }

    }

}

запомнить

Если объекту назначен идентификатор или составной ключ, идентификатор ДОЛЖЕН БЫТЬ НАЗНАЧЕН экземпляр объекта ПЕРЕД вызовом save ().

Итак, мы создали конструктор JoinedUserRoleId, подобный этому, чтобы позаботиться о нем

public JoinedUserRoleId(User user, Role role) {
    this.user = user;
    this.role = role;
}

И, наконец, класс роли

@Entity
@Table(name="ROLE")
public class Role {

    @Id
    @GeneratedValue
    private Integer id;

    @OneToMany(cascade=CascadeType.ALL, mappedBy="JoinedUserRoleId.role")
    private List<JoinedUserRole> joinedUserRoleList = new ArrayList<JoinedUserRole>();

    // no-arg required constructor
    public Role() {}

    public Role(Integer id) {
        this.id = id;
    }

    // addUser sets up bidirectional relationship
    public void addUser(User user) {
        // Notice a JoinedUserRole object
        JoinedUserRole joinedUserRole = new JoinedUserRole(new JoinedUserRole.JoinedUserRoleId(user, this));

        joinedUserRole.setUser(user);
        joinedUserRole.setRole(this);

        joinedUserRoleList.add(joinedUserRole);
    }

}

В соответствии с его проверкой, давайте напишем следующее

User user = new User();
Role role = new Role();

// code in order to save a User and a Role
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();

Serializable userId  = session.save(user);
Serializable roleId = session.save(role);

session.getTransaction().commit();
session.clear();
session.close();

// code in order to set up bidirectional relationship
Session anotherSession = HibernateUtil.getSessionFactory().openSession();
anotherSession.beginTransaction();

User savedUser = (User) anotherSession.load(User.class, userId);
Role savedRole = (Role) anotherSession.load(Role.class, roleId);

// Automatic dirty checking
// It will set up bidirectional relationship
savedUser.addRole(savedRole);

anotherSession.getTransaction().commit();
anotherSession.clear();
anotherSession.close();

Уведомление в соответствии с приведенным выше кодом НИКАКОЙ ССЫЛКИ на класс JoinedUserRole.

Если вы хотите получить роль JoinedUserRole, попробуйте следующее

Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();

Integer userId;
Integer roleId;

// Lets say you have set up both userId and roleId
JoinedUserRole joinedUserRole = (JoinedUserRole) session.get(JoinedUserRole.class, new JoinedUserRole.JoinedUserRoleId(userId, roleId));

// some operations

session.getTransaction().commit();
session.clear();
session.close();

с уважением,

12
ответ дан 30 November 2019 в 07:18
поделиться
Другие вопросы по тегам:

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