When persisting Hibernate Entity, I want to use @GeneratedValue annotation for @Id annotated field and set it to CHAR type column.
However, due to the specifications of the business FW adopted, there is a separate sequence serial number acquisition table (sequence_mng) instead of SEQUENCE of DBMS (SQL Server), and sequence_mng is not used to maintain consistency when creating a new record. It must not be.
The column should be BIGINT too! I think, but it can't be helped because there is something like "zero padding and fixed digit" belief.
・ JDK1.8 ・ Hibernate (5.2.10.FINAL) · SQL Server 2016
sequence_mng
CREATE TABLE sequence_mng (
colname VARCHAR(40) NOT NULL,
nextvalue BIGINT NOT NULL,
PRIMARY KEY colname
);
partner
CREATE TABLE m_partner (
partner_cd CHAR(6) NOT NULL,
partner_nm NVARCHAR(60) NOT NULL,
-- OMITTED
PRIMARY KEY partner_cd
);
Like this, when you try to make it permanent by calling save () etc. -Get the record where the colname of sequence_mng is "partner_cd" -Store nextvalue in partnerCd of Partner.class ・ Next value ++ I want to make it work based on Annotation.
And with this pattern, I feel like I can use GenerationType.TABLE
.
just like this
Partner.java(Failure)
@Entity
@Table(name = "partner")
public class Partner {
@Id
@GeneratedValue(strategy = GenerationType.TABLE, generator = "SEQ_TBL_PARTNER")
@TableGenerator(name = "SEQ_TBL_PARTNER",
table = "sequence_mng",
pkColumnName = "colname",
valueColumnName = "nextvalue",
pkColumnValue = "partner_cd")
@Column(name = "partner_cd", unique = true, nullable = false, length = 6)
private Integer partnerCd;
@Column(name = "partner_nm", nullable = false)
private String partnerNm;
//The following is omitted
}
However, the substance of @TableGenerator
org.hibernate.id.enhanced.TableGenerator
Actually with'org.hibernate.id.IdentifierGeneratorHelper#getIntegralDataTypeHolder'
@Id field does not allow except long (Long), BigDecimal
IdentifierGenerationException("Unknown integral data type for ids : StringType())
It doesn't move next to it.
As mentioned above, the column attributes cannot be changed.
Therefore, I will create a StringTableGenerator that inherits TableGenerator and make it work. StringTableGenerator.java Create a StringTableGenerator that inherits from TableGenerator.
StringTableGenerator.java
package sample.hibernate.id;
import org.hibernate.MappingException;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.id.IdentifierGeneratorHelper;
import org.hibernate.id.IntegralDataTypeHolder;
import org.hibernate.id.enhanced.TableGenerator;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.type.BigDecimalType;
import org.hibernate.type.Type;
import java.io.Serializable;
import java.util.Properties;
/**
* TableGenerator (Supports string columns)
*/
public class StringTableGenerator extends TableGenerator {
@Override
public void configure(Type type, Properties params, ServiceRegistry serviceRegistry)
throws MappingException {
super.configure(new BigDecimalType() , params, serviceRegistry);
}
@Override
public Serializable generate(SharedSessionContractImplementor session, Object obj) {
return super.generate(session, obj).toString();
}
}
Since StringType comes as the first argument, replace it with BigDecimalType () before passing it to the parent class (^^)
The value returned from the parent class is BigDecimal, so replace it with a String before returning it. that's all.
Then, rewrite the Entity that actually generates the sequence as follows.
Partner.java
@Entity
@Table(name = "partner")
public class Partner implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.TABLE, generator = "CUSTOM_SEQ")
@GenericGenerator(strategy = "sample.hibernate.id.StringTableGenerator",
name = "CUSTOM_SEQ", parameters = {
@Parameter(name = "segment_value", value = "partner_cd"),
@Parameter(name = "table_name", value = "sequence_mng"),
@Parameter(name = "segment_column_name", value = "colname"),
@Parameter(name = "value_column_name", value = "nextvalue")
})
@Column(name = "partner_cd", unique = true, nullable = false, length = 6)
private String partnerCd;
@Column(name = "partner_nm", nullable = false)
private String partnerNm;
(The following is omitted)
Change from @TableGenerator, which has a fixed class, to @GenericGenerator, and specify that the StringTableGenerator created earlier should be used. Note that the parameters also change their names.
With the above changes, a serial number will be generated and set in the String field as well.
Click here for Sequence Generator (almost original material) https://stackoverflow.com/questions/12517421/how-to-map-a-string-to-db-sequence-in-hibernate
Easy-to-understand description of Table Generator http://d.hatena.ne.jp/taedium/20070627/p1
This is also an easy-to-understand Table Generator http://qiita.com/KevinFQ/items/a6d92ec7b32911e50ffe
Hibernate changes the package structure and class name from time to time, so The materials out there quickly become obsolete.
If you think it's strange-it doesn't move, it's faster to look at the source. This time, the @Parameter name attribute did.
I couldn't find any other TableGenerator and StringType support, so I'll enter it in the hope that it will be useful to someone. then.
Recommended Posts