HibernateにてDAOを生成-複数結合モデル

前回で単一のモデルについてDAOを作成しました。
今回は複数結合したモデルに対してDAOを作成していきます。
以下のDBスキーマに対してモデルを作成します。
DBスキーマ:
 
プロジェクト構成:
  • entityがモデルクラスを格納するディレクトリ
  • repositoryがif定義クラスを格納するディレクトリ
 

src/main/java.
└── com
    └── soulimpact
        └── soulmate
            ├── entity
            │   ├── SMDepartment.java
            │   ├── SMFunction.java
            │   ├── SMRole.java
            │   ├── SMRoleFunction.java
            │   └── SMUser.java
            ├── repository
            │   └── SMUserRepository.java
            └── service
                └── SMUserService.java
 

親となるSMUserを修正

SMUser.java

修正の際@JoinColumnのinsertable, updatableをfalseにしないと例外が発生してしまいます。

Create, Update時に結合先のモデルにも反映に影響するかどうかの指定となります。

 
package com.soulimpact.soulmate.entity;

import lombok.Data;

import javax.persistence.*;
import javax.websocket.OnError;
import java.util.Date;
import java.util.UUID;

@Entity
@Data
@Table(name="users", schema="public")
public class SMUser {

   @Id
   @Column(name="user_id")
   private String userId;

   @Column(name="profile")
   private String profile;
   
   @Column(name="password")
   private String password;
   
   @Column(name="user_name")
   private String userName;

   @Column(name="department_id")
   private UUID departmentId;

   @Column(name="role_id")
   private UUID roleId;

   @Column(name="created_time")
   private Date createdTime;

   @Column(name="updated_time")
   private Date updatedTime;

   @Column(name="deleted_time")
   private Date deletedTime;

   @ManyToOne
   @JoinColumn(name = "department_id", referencedColumnName = "department_id", insertable = false, updatable = false)
   private SMDepartment department;

   @ManyToOne
   @JoinColumn(name = "role_id", referencedColumnName = "role_id", insertable = false, updatable = false)
   private SMRole role;

}

各子供のモデルクラス定義

SMDepartment.java
部署モデル
 
package com.soulimpact.soulmate.entity;

import lombok.Data;

import javax.persistence.*;
import java.util.Date;
import java.util.List;
import java.util.UUID;

@Entity
@Data
@Table(name="department", schema="public")
public class SMDepartment {

   @Id
   @Column(name="department_id")
   private UUID departmentId;

   @Column(name="department_name")
   private String departmentName;

   @Column(name="created_time")
   private Date createdTime;

   @Column(name="updated_time")
   private Date updatedTime;

   @Column(name="deleted_time")
   private Date deletedTime;

// @OneToMany(mappedBy="department", cascade = CascadeType.ALL)
// private List<SMUser> user;

}
SMRole.java
権限モデル
権限と機能の関連モデルエンティティと結合する箇所を@JoinCloumnで定義しています。
 
package com.soulimpact.soulmate.entity;

import lombok.Data;

import javax.persistence.*;
import java.util.Date;
import java.util.List;
import java.util.UUID;

@Entity
@Data
@Table(name="role", schema="public")
public class SMRole {

   @Id
   @Column(name="role_id")
   private UUID roleId;

   @Column(name="role_name")
   private String roleName;

   @Column(name="created_time")
   private Date createdTime;

   @Column(name="updated_time")
   private Date updatedTime;

   @Column(name="deleted_time")
   private Date deletedTime;

   @OneToMany
   @JoinColumn(name = "role_id", referencedColumnName = "role_id", insertable = false, updatable = false)
   private List<SMRoleFunction> roleFunctionList;

}
SMFunction.java
機能モデル
 
package com.soulimpact.soulmate.entity;

import lombok.Data;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import java.util.Date;
import java.util.UUID;

@Entity
@Data
@Table(name="function", schema="public")
public class SMFunction {

   @Id
   @Column(name="function_id")
   private UUID functionId;

   @Column(name="explanation")
   private String explanation;

   @Column(name="created_time")
   private Date createdTime;

   @Column(name="updated_time")
   private Date updatedTime;

   @Column(name="deleted_time")
   private Date deletedTime;

}
SMRoleFunction.java
権限と機能の関連モデル
子供の機能モデルの結合を@JoinColumnで指定しています。
 
package com.soulimpact.soulmate.entity;

import lombok.Data;

import javax.persistence.*;
import java.util.Date;
import java.util.List;
import java.util.UUID;

@Entity
@Data
@Table(name="role_function", schema="public")
public class SMRoleFunction {

   @Id
   @Column(name="function_id")
   private UUID functionId;

   @Column(name="role_id")
   private UUID roleId ;

   @Column(name="crud_type")
   private String crudType ;

   @Column(name="created_time")
   private Date createdTime;

   @Column(name="updated_time")
   private Date updatedTime;

   @Column(name="deleted_time")
   private Date deletedTime;

   @ManyToOne
   @JoinColumn(name = "function_id", referencedColumnName = "function_id", insertable = false, updatable = false)
   private SMFunction function;
}

利用方法

SMUserService.java

単一モデル取得時とは異なり@Transactionalをメソッドに指定してください。

結合先のモデルは遅延取得となるためトランザクション範囲で全体を取得してください。

 
@Transactional
public SMUser findByIdWithRoleInfo(String id) {
   Optional<SMUser> user = userRepository.findById(id);
   if(!user.isEmpty()) {
      return user.get();
   }
   return null;
}