1. ホーム
  2. hibernate

[解決済み] 多対多のアソシエーションテーブルを追加カラムでマッピングする

2022-05-28 04:25:50

質問

私のデータベースには3つのテーブルがあります。 UserとServiceのエンティティは多対多の関係を持っており、以下のようにSERVICE_USERテーブルと結合されています。

ユーザ - サービスユーザ - サービス

SERVICE_USERテーブルには、BLOCKEDカラムが追加されています。

このようなマッピングを行う最良の方法は何でしょうか? これらは私のEntityクラスです。

@Entity
@Table(name = "USERS")
public class User implements java.io.Serializable {

private String userid;
private String email;

@Id
@Column(name = "USERID", unique = true, nullable = false,)
public String getUserid() {
return this.userid;
}

.... some get/set methods
}

@Entity
@Table(name = "SERVICES")
public class CmsService implements java.io.Serializable {
private String serviceCode;

@Id
@Column(name = "SERVICE_CODE", unique = true, nullable = false, length = 100)
public String getServiceCode() {
return this.serviceCode;
}
.... some additional fields and get/set methods
}

私はこの例に従って http://giannigar.wordpress.com/2009/09/04/m ... using-jpa/ 以下は、いくつかのテストコードです。

User user = new User();
user.setEmail("e2");
user.setUserid("ui2");
user.setPassword("p2");

CmsService service= new CmsService("cd2","name2");

List<UserService> userServiceList = new ArrayList<UserService>();

UserService userService = new UserService();
userService.setService(service);
userService.setUser(user);
userService.setBlocked(true);
service.getUserServices().add(userService);

userDAO.save(user);

問題は、hibernateがUserオブジェクトとUserServiceオブジェクトを永続化することです。CmsServiceオブジェクトでは成功しません。

EAGERフェッチを使ってみましたが、うまくいきません。

上記で提供されたマッピングで、私が期待している動作を実現することは可能でしょうか?

追加カラムを持つ多対多の結合テーブルをマッピングする、よりエレガントな方法があるのではないでしょうか?

どのように解決するのですか?

SERVICE_USERテーブルは純粋な結合テーブルではなく、追加の機能フィールド(ブロック)を持っているため、エンティティとしてマッピングし、ユーザとサービスの間の多対多の関連付けを2つのOneToMany関連付けに分解する必要があります。1人のユーザーは多くのユーザーサービスを持ち、1つのサービスは多くのユーザーサービスを持ちます。

最も重要な部分である、エンティティ間の関係のマッピングと初期化(つまり、問題を抱えた部分)を見せてくれていません。そこで、どのように見えるべきかをお見せします。

関係を双方向にする場合、次のようになります。

class User {
    @OneToMany(mappedBy = "user")
    private Set<UserService> userServices = new HashSet<UserService>();
}

class UserService {
    @ManyToOne
    @JoinColumn(name = "user_id")
    private User user;

    @ManyToOne
    @JoinColumn(name = "service_code")
    private Service service;

    @Column(name = "blocked")
    private boolean blocked;
}

class Service {
    @OneToMany(mappedBy = "service")
    private Set<UserService> userServices = new HashSet<UserService>();
}

リレーションシップにカスケードをかけない場合は、すべてのエンティティを永続化/保存する必要があります。リレーションシップの所有者側(ここではUserService側)のみを初期化する必要がありますが、両側のまとまりを確認することも良い練習になります。

User user = new User();
Service service = new Service();
UserService userService = new UserService();

user.addUserService(userService);
userService.setUser(user);

service.addUserService(userService);
userService.setService(service);

session.save(user);
session.save(service);
session.save(userService);