はじめに
「Spring Data JPA」でデータを登録するときに、
シーケンスで採番したものに接頭辞(プレフィックス)つけた時のコードをまとめています。
環境
Java 8
PostgreSQL 10.5
やったこと
独自Generatorを実装する。(接頭辞を付ける人)
SequenceStyleGeneratorを継承します。
シーケンスで採番をするのは内部(スーパークラス)の処理をそのまま使います。
独自Generatorは採番されたものに prefix を付ける役割です。
EntityにGeneratorの指定とパラメータを記載する
Entityでシーケンスの指定や接頭辞、フォーマットの指定をします。
シーケンスを指定しないと hibernate_sequence
を使おうとします。
(ここでちょっとハマった)
ソース
実装したソースです。
独自Generator
import java.io.Serializable;
import java.util.Properties;
import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.id.enhanced.SequenceStyleGenerator;
import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.type.LongType;
import org.hibernate.type.Type;
public class PrefixedIdGenerator extends SequenceStyleGenerator {
public static final String VALUE_PREFIX_PARAMETER = "valuePrefix";
public static final String VALUE_PREFIX_DEFAULT = "";
private String valuePrefix;
public static final String NUMBER_FORMAT_PARAMETER = "numberFormat";
public static final String NUMBER_FORMAT_DEFAULT = "%d";
private String numberFormat;
@Override
public Serializable generate(SharedSessionContractImplementor session, Object object) throws HibernateException {
return valuePrefix + String.format(numberFormat, super.generate(session, object));
}
@Override
public void configure(Type type, Properties params, ServiceRegistry serviceRegistry) throws MappingException {
super.configure(LongType.INSTANCE, params, serviceRegistry);
valuePrefix = ConfigurationHelper.getString(VALUE_PREFIX_PARAMETER, params, VALUE_PREFIX_DEFAULT);
numberFormat = ConfigurationHelper.getString(NUMBER_FORMAT_PARAMETER, params, NUMBER_FORMAT_DEFAULT);
}
}
Entity
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.Data;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Parameter;
@Entity
@Data
@Table(name = "trial")
public class Trial {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq_trial")
@GenericGenerator(
name = "seq_trial",
strategy = "PrefixedIdGenerator",
parameters = {
@Parameter(name = PrefixedIdGenerator.SEQUENCE_PARAM, value = "seq_trial"),
@Parameter(name = PrefixedIdGenerator.VALUE_PREFIX_PARAMETER, value = "B_"),
@Parameter(name = PrefixedIdGenerator.NUMBER_FORMAT_PARAMETER, value = "%05d") })
@Column(name = "trial_id")
private String trialId;
@Column(name = "trial_name")
private String trialName;
}
Service
@Service
public class TrialService {
@Autowired
private TrialRepository repository;
@Transactional
public void insert() {
Trial entity = new Trial();
entity.setTrialName("trial_xxxxxxxx");
repository.save(entity);
}
}
実行時ログ
2019/05/24 17:54:18.505 [http-nio-8099-exec-1] DEBUG SqlStatementLogger 92 :
select
nextval ('seq_test')
2019/05/24 17:54:22.313 [http-nio-8099-exec-1] DEBUG SqlStatementLogger 92 :
insert
into
trial
(trial_name, trial_id)
values
(?, ?)
2019/05/24 17:54:22.318 [http-nio-8099-exec-1] TRACE BasicBinder 65 : binding parameter [1] as [VARCHAR] - [trial_xxxxxxxx]
2019/05/24 17:54:22.319 [http-nio-8099-exec-1] TRACE BasicBinder 65 : binding parameter [2] as [VARCHAR] - [B_00001]
参考にしたサイト
How to Implement a Custom, Sequence-Based ID Generator
以上