我对hibernate很新,我正在尝试将我的JDBC项目转换为Hibernate。
我正在使用注释,我设法注释基本的东西,但是,我现在被困在更重的物体上,我不知道如何注释它们。 这是班级:
@Entity
@Table(name = "person")
public class Person {
public Person{
}
// THIS WILL BE SOON INJECTED BY SPRING
private static transient PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
private static transient EmailValidator validator = EmailValidator.getInstance();
@Id
@Column(name = "person_id")
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@Column(name = "private_name", nullable = false, length = 20)
private String privateName;
@Column(name = "middle_name", length = 20)
private String middleName;
@Column(name = "family_name", nullable = false, length = 20)
private String familyName;
@Column(name = "age", nullable = false)
private int age;
@Column(name = "address1", nullable = false)
private String address1;
@Column(name = "address2")
private String address2;
//How do I annotate this ? --> Google LIBPHONENUMBER
private PhoneNumber phone;
// How do I annotate this ? --> This is a normal PNG image file.
private File image;
编辑: 该文件先前已映射为BLOB。 PhoneNumber以前是作为String保存的,并使用PhoneNumber构造函数转换为Phonenumber。
答案 0 :(得分:4)
关于使用@Lob的其他注释对于文件类型是正确的。如果您可以更改架构以不在DB中保存文件数据,那也是正确的。那么您可能应该这样做。
要将PhoneNumber类映射到数据库字段,您将需要使用Hibernate自定义UserType。它基本上告诉Hibernate如何为它不知道的类做对象< - > db映射。在Person中告诉PhoneNumber字段以使用自定义用户类型很容易:
@Type(type = PhoneNumberType.CLASS_NAME)
@Column
private PhoneNumber phone;
这假设电话号码的单列存储非常简单。
要编写PhoneNumberType,您需要实现UserType。使用汇编/反汇编/ deepCopy看起来势不可挡,但您关心的主要部分是nullSetGet / Set,returnedClass和sqlTypes。在自定义类型中,您最终会得到一些类似的代码:
@Override
public Class<?> returnedClass() {
return PhoneNumber.class;
}
@Override
public int[] sqlTypes() {
return new int[] { Types.VARCHAR };
}
@Override
public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws HibernateException, SQLException {
final String value = rs.getString(names[0]);
return /* PhoneNumber instance created from string. */
}
@Override
public void nullSafeSet(PreparedStatement st, Object value, int index) throws HibernateException, SQLException {
if (value == null) {
st.setNull(index, Types.VARBINARY);
return;
}
st.setString(index, ((PhoneNumber) value).toString());
}
您可以通过google,stackoverflow和hibernate javadocs找到有关如何实现其他方法的大量信息。这并不难。
更新:多列用户类型
实施CompositeUserType
而非UserType
。您关心的方法有一些变化。首先,您需要定义多个属性名称和类型:
public String[] getPropertyNames() {
return new String[] { "number", "code" };
}
public Type[] getPropertyTypes() {
return new Type[] { StandardBasicTypes.STRING,
StandardBasicTypes.STRING };
}
还需要getPropertyValue
/ setPropertyValue
来实施。您的nullSafeXxxx实现将更改为读取和写入两个属性而不是一个:
@Override
public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws HibernateException, SQLException {
// Access column in order defined in getPropertyNames()
final String number = rs.getString(names[0]);
final String code = rs.getString(names[1]);
return /* PhoneNumber instance created from number and country code. */
}
答案 1 :(得分:1)
就个人而言,我只在对象中存储文件名,并将文件保存在文件所在的文件系统中。
否则,将其映射为Hibernate blob(@Lob
)并且您希望它是一个字节数组(将转换为blob)。
IMO通常会产生比它更值得的麻烦,但这部分取决于数据库,驱动程序修订等。
答案 2 :(得分:0)
您可以像这样注释PhoneNumber:
@ManyToOne
@JoinColumn(name = "PHONE_NUMBER")
private PhoneNumber phone;
假设PHONE_NUMBER列存在并映射到电话号码的ID。 PhoneNumber类也需要注释。这假设您希望在不同实体之间共享电话号码(多对一)。
关于文件,您可能需要决定是否要将文件数据实际存储在db中(通常不是一个好主意)。否则,你可以只存储一个带有文件路径的字符串。
答案 3 :(得分:0)
只需为PhoneNumber创建一个Hibernate UserType
import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import org.apache.commons.lang.ObjectUtils;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.type.StringRepresentableType;
import org.hibernate.usertype.UserType;
import com.google.i18n.phonenumbers.NumberParseException;
import com.google.i18n.phonenumbers.PhoneNumberUtil;
import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber;
import com.tg.util.TGPhoneUtils;
public class PhoneNumberUserType implements UserType, StringRepresentableType<PhoneNumber>, Serializable {
private static final long serialVersionUID = -364436436346432L;
@Override
public boolean equals(Object x, Object y) throws HibernateException {
return ObjectUtils.equals(x, y);
}
@Override
public int hashCode(Object object) throws HibernateException {
return object.hashCode();
}
@Override
public Object deepCopy(Object value) throws HibernateException {
return value;
}
@Override
public boolean isMutable() {
return false;
}
@Override
public Serializable disassemble(Object value) throws HibernateException {
return (Serializable) value;
}
@Override
public Object assemble(Serializable cached, Object value) throws HibernateException {
return cached;
}
@Override
public Object replace(Object original, Object target, Object owner) throws HibernateException {
return original;
}
@Override
public String toString(PhoneNumber value) throws HibernateException {
return value.toString();
}
@Override
public Class<?> returnedClass() {
return PhoneNumber.class;
}
@Override
public int[] sqlTypes() {
return new int[] { Types.VARCHAR };
}
@Override
public PhoneNumber fromStringValue(String number) throws HibernateException {
try {
return PhoneNumberUtil.getInstance().parse(number, "US");
} catch (NumberParseException e) {
throw new HibernateException(e);
}
}
@Override
public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor arg2, Object owner) throws HibernateException, SQLException {
final String number = rs.getString(names[0]);
if (number == null) {
return null;
}
return TGPhoneUtils.parsePhoneNumber(number);
}
@Override
public void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor si) throws HibernateException, SQLException {
if (value == null) {
st.setNull(index, Types.VARCHAR);
return;
}
st.setString(index, TGPhoneUtils.formatPhoneNumber((PhoneNumber)value));
}
}
然后这里是帮助类
import com.google.i18n.phonenumbers.PhoneNumberUtil;
import com.google.i18n.phonenumbers.PhoneNumberUtil.PhoneNumberFormat;
import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber;
public class TGPhoneUtils {
public static PhoneNumber parsePhoneNumber(String phoneNum) {
if (phoneNum == null) {
return null;
}
try {
return PhoneNumberUtil.getInstance().parse(phoneNum, "US");
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static String formatPhoneNumber(PhoneNumber phoneNum) {
if (phoneNum == null) {
return null;
}
return PhoneNumberUtil.getInstance().format(phoneNum, PhoneNumberFormat.E164);
}
}