Reputation: 35
I'm trying to create a custom user type for my database called CompanyType. I will use it to store only one unique String as an identifier for my final object (in code it is LEGAL and INDIVIDUAL).
Full class of CompanyType:
public class CompanyType implements UserType {
private String typeId;
private String typeName;
public static final CompanyType LEGAL = new CompanyType("LEGAL", "Some legal type");
public static final CompanyType INDIVIDUAL = new CompanyType("INDIVIDUAL", "Some individual type");
public CompanyType(String typeId, String typeName) {
this.typeId = typeId;
this.typeName = typeName;
}
public String getTypeId() {
return typeId;
}
public String getTypeName() {
return typeName;
}
@Override
public int[] sqlTypes() {
return new int[]{Types.VARCHAR};
}
@Override
public Class returnedClass() {
return String.class;
}
@Override
public boolean equals(Object o, Object o1) throws HibernateException {
return o.equals(o1);
}
@Override
public int hashCode(Object o) throws HibernateException {
return o.hashCode();
}
@Override
public Object nullSafeGet(ResultSet resultSet, String[] strings, SharedSessionContractImplementor sharedSessionContractImplementor, Object o) throws HibernateException, SQLException {
if(resultSet.getString(strings[0]).equals("LEGAL")) return LEGAL;
else return INDIVIDUAL;
}
@Override
public void nullSafeSet(PreparedStatement preparedStatement, Object o, int i, SharedSessionContractImplementor sharedSessionContractImplementor) throws HibernateException, SQLException {
preparedStatement.setString(i, this.getTypeId());
}
@Override
public Object deepCopy(Object o) throws HibernateException {
CompanyType toCopy = (CompanyType) o;
return new CompanyType(toCopy.getTypeId(), toCopy.getTypeName());
}
@Override
public boolean isMutable() {
return true;
}
@Override
public Serializable disassemble(Object o) throws HibernateException {
return (Serializable) o;
}
@Override
public Object assemble(Serializable serializable, Object o) throws HibernateException {
return serializable;
}
@Override
public Object replace(Object o, Object o1, Object o2) throws HibernateException {
return deepCopy(o);
}
}
And then I'm trying to use it in my entity - Contragent.java
@Entity
public class Contragent {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
private String name;
private String INN;
private String OGRN;
@Type(type = "com.test.test1.CompanyType")
private CompanyType companyType;
... other code
When I'm running my project, it prints an exception:
2021-03-15 02:15:07.831 ERROR 12824 --- [ restartedMain] o.s.boot.SpringApplication : Application run failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.MappingException: Unable to instantiate custom type: com.test.test1.CompanyType
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1786) ~[spring-beans-5.3.4.jar:5.3.4]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:602) ~[spring-beans-5.3.4.jar:5.3.4]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524) ~[spring-beans-5.3.4.jar:5.3.4]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.4.jar:5.3.4]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.4.jar:5.3.4]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.4.jar:5.3.4]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.4.jar:5.3.4]
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1153) ~[spring-context-5.3.4.jar:5.3.4]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:907) ~[spring-context-5.3.4.jar:5.3.4]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:582) ~[spring-context-5.3.4.jar:5.3.4]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:144) ~[spring-boot-2.4.3.jar:2.4.3]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:767) ~[spring-boot-2.4.3.jar:2.4.3]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759) ~[spring-boot-2.4.3.jar:2.4.3]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:426) ~[spring-boot-2.4.3.jar:2.4.3]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:326) ~[spring-boot-2.4.3.jar:2.4.3]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1311) ~[spring-boot-2.4.3.jar:2.4.3]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1300) ~[spring-boot-2.4.3.jar:2.4.3]
at com.test.test1.Test1Application.main(Test1Application.java:11) ~[classes/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) ~[spring-boot-devtools-2.4.3.jar:2.4.3]
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.MappingException: Unable to instantiate custom type: com.test.test1.CompanyType
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:421) ~[spring-orm-5.3.4.jar:5.3.4]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396) ~[spring-orm-5.3.4.jar:5.3.4]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:341) ~[spring-orm-5.3.4.jar:5.3.4]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1845) ~[spring-beans-5.3.4.jar:5.3.4]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1782) ~[spring-beans-5.3.4.jar:5.3.4]
... 22 common frames omitted
Caused by: org.hibernate.MappingException: Unable to instantiate custom type: com.test.test1.CompanyType
at org.hibernate.type.TypeFactory.custom(TypeFactory.java:185) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
at org.hibernate.type.TypeFactory.byClass(TypeFactory.java:78) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
at org.hibernate.type.TypeResolver.heuristicType(TypeResolver.java:126) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
at org.hibernate.mapping.SimpleValue.getType(SimpleValue.java:484) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
at org.hibernate.mapping.SimpleValue.isValid(SimpleValue.java:466) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
at org.hibernate.mapping.Property.isValid(Property.java:227) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:624) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
at org.hibernate.mapping.RootClass.validate(RootClass.java:267) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
at org.hibernate.boot.internal.MetadataImpl.validate(MetadataImpl.java:354) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:298) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:468) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1259) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:58) ~[spring-orm-5.3.4.jar:5.3.4]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365) ~[spring-orm-5.3.4.jar:5.3.4]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409) ~[spring-orm-5.3.4.jar:5.3.4]
... 26 common frames omitted
Caused by: java.lang.InstantiationException: com.test.test1.CompanyType
at java.base/java.lang.Class.newInstance(Class.java:571) ~[na:na]
at org.hibernate.type.TypeFactory.custom(TypeFactory.java:177) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
... 40 common frames omitted
Caused by: java.lang.NoSuchMethodException: com.test.test1.CompanyType.<init>()
at java.base/java.lang.Class.getConstructor0(Class.java:3349) ~[na:na]
at java.base/java.lang.Class.newInstance(Class.java:556) ~[na:na]
... 41 common frames omitted
Process finished with exit code 0
Upvotes: 1
Views: 966
Reputation: 13041
I would suggest you to use an enum for this case:
public enum CompanyType {
LEGAL("Some legal type"),
INDIVIDUAL("Some individual type");
private final String name;
CompanyType(String name)
{
this.name = name;
}
public String getCompanyName()
{
return name;
}
}
and then use it in this way:
@Entity
public class Contragent {
// ...
@Enumerated(EnumType.STRING)
@Column(name = "company_type")
private CompanyType companyType;
}
Upvotes: 1