我对Hibernate很新,事实证明这不是一个简单的学习技术......在项目中我使用的是hibernate版本4.2.0.CR1。我正在尝试为所有数据库实体创建一个基类,因为它们都应该包含一些标识符和创建日期。奇怪的是,起初,我创建了没有任何基类的类User和UserPicture,并且它工作得很好,现在我添加了它,即使它应该像以前一样工作,它也不会o_O并且它继续投掷关于我的照片列表的一些奇怪的例外,之前没有抛出...... 所以我继续关注stacktrace:
org.hibernate.MappingException: Could not determine type for: java.util.List, at table: User, for columns: [org.hibernate.mapping.Column(profilePicture)]
at org.hibernate.mapping.SimpleValue.getType(SimpleValue.java:314)
at org.hibernate.mapping.SimpleValue.isValid(SimpleValue.java:292)
at org.hibernate.mapping.Property.isValid(Property.java:239)
at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:469)
at org.hibernate.mapping.UnionSubclass.validate(UnionSubclass.java:61)
at org.hibernate.cfg.Configuration.validate(Configuration.java:1283)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1734)
at love.commons.database.DBManager.<init>(DBManager.java:28)
at love.commons.database.DBManagerTest.<clinit>(DBManagerTest.java:19)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:27)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
AbstractEntity:
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class AbstractEntity implements Serializable{
private static final long serialVersionUID = 1L;
protected Long id;
protected Date creationDate = new Date();
@Id
@Column(name="id")
@GeneratedValue(strategy=GenerationType.TABLE)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Column
@NotNull
@Temporal(TemporalType.DATE)
public Date getCreationDate() {
return creationDate;
}
public void setCreationDate(Date creationDate) {
this.creationDate = creationDate;
}
}
用户:
@Entity
@Table(name="User")
public class User extends AbstractEntity {
private static final long serialVersionUID = 1L;
@Column (unique=true, length=30)
@NotNull
private String login;
@Column (length=32)
@NotNull
private String password;
@NotNull
@Email
@Column (unique=true, length=80)
private String email;
@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="owner")
private List<UserPicture> profilePictures = new LinkedList<UserPicture>();
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Transient
public void encryptPassword() {
this.password = md5(password);
}
public List<UserPicture> getProfilePicture() {
return Collections.unmodifiableList(profilePictures);
}
public void addProfilePicture(UserPicture profilePicture) {
profilePicture.setOwner(this);
profilePictures.add(profilePicture);
}
@Transient
private String md5(String input) {
String md5 = null;
if(null == input) return null;
try {
MessageDigest digest = MessageDigest.getInstance("MD5");
digest.update(input.getBytes(), 0, input.length());
md5 = new BigInteger(1, digest.digest()).toString(16);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return md5;
}
}
UserPicture:
@Entity
public class UserPicture extends AbstractEntity {
private static final long serialVersionUID = 1L;
@Column(length=734004)
private byte [] picture = null;
@ManyToOne(fetch=FetchType.LAZY)
@Column(name="owner")
@JoinColumn(nullable=false,name="id")
private User owner;
public UserPicture() {
picture = null;
}
public UserPicture(InputStream stream) {
try {
this.picture = new byte[stream.available()];
stream.read(picture);
} catch (IOException e) {
e.printStackTrace();
}
}
public UserPicture(byte [] picture) {
this.picture = picture;
}
public byte[] getPicture() {
return picture;
}
public void setPicture(byte[] picture) {
this.picture = picture;
}
public User getOwner() {
return owner;
}
public void setOwner(User owner) {
this.owner = owner;
}
}
那么我做错了什么?为什么我继续获得例外?
答案 0 :(得分:5)
不得使用@Entity
和@Inheritance
注释AbstractEntity。必须使用@MappedSuperclass
进行注释。实际上,这种继承仅用于继承公共属性,这就是MappedSuperclass
的用途。
您获得的异常是由于映射注释的位置缺乏连贯性造成的。基类超类注释了getter,子类注释了这些字段。 Hibernate使用Id注释的位置来确定实体的访问类型。由于@Id在getter上,它只考虑放在getter上的注释,并忽略放在字段上的注释。将所有注释放在字段(我建议)或getter上。
此外,你的获取者名字很糟糕。它应该是getProfilePictures()
而不是getProfilePicture()
。
答案 1 :(得分:1)
来自Hibernate 5.2 documentation:
默认情况下,@ Id注释的位置提供默认值 访问策略。
对于您的情况,hibernate将对AccessType.PROPERTY
和UserPicture
实体使用User
因此例外,要使用字段映射策略,您应该明确定义@Access策略:
@Entity
@Table(name="User")
@Access( AccessType.FIELD )
public class User extends AbstractEntity {
...
}
@Entity
@Access( AccessType.FIELD )
public class UserPicture extends AbstractEntity {
....
}
答案 2 :(得分:0)
我有同样的问题,我发现hibernate试图使用Parent使用属性accessorso我通过使用@Access批注强制使用字段来解决问题
@Entity
@Table(name = "MyTable")
@Access(AccessType.FIELD)
public class MyEntity{
......
}
答案 3 :(得分:0)
您可以尝试在List声明上方添加@ElementCollection映射。