我正在尝试使用JPA来持久化User对象并遇到问题。 User引用一组Role对象,它是一个抽象类,它将具有多个子类。目前,我只有一个 - 管理员。
这是User类:
@Entity(name = "USERS")
public class User implements Serializable{
@Id
@Column(name = "USERNAME")
private String username;
@Column(name = "PASSWORD")
private String password;
@Column(name = "FIRST_NAME")
private String firstName;
@Column(name = "LAST_NAME")
private String lastName;
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name = "ROLE_ID")
private Set<Role> roles;
public User(){
roles = new HashSet<Role>();
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Set<Role> getRoles(){
return roles;
}
public void setRoles(Set<Role> roles){
this.roles = roles;
}
public void addRole(Role role){
roles.add(role);
}
}
这是角色:
@Entity(name = "ROLES")
@Inheritance(strategy=InheritanceType.JOINED)
public abstract class Role implements Serializable{
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name = "ROLE_ID")
int id;
public void setId(int id){
this.id = id;
}
public int getId(){
return id;
}
}
这是Admin(现在是空的,但稍后会添加内容)。
@Entity(name = "ADMINS")
public class Admin extends Role{
}
现在这里是我正在创建对象并试图保留它们的代码。我希望能够持久保存User对象并让它的Role对象自动持久化 - 我相信用户中的CascaseType.ALL可以做到这一点。
public class JPAManager {
public void persist(Serializable s){
EntityManagerFactory emf = getEntityManagerFactory();
EntityManager em = emf.createEntityManager();
EntityTransaction et = em.getTransaction();
et.begin();
em.persist(s);
et.commit();
em.close();
emf.close();
}
protected EntityManagerFactory getEntityManagerFactory(){
return Persistence.createEntityManagerFactory("main");
}
}
最后,这是主要方法:
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("context.xml");
User user = new User();
user.setUsername("Chris842");
user.setPassword("123456");
user.setFirstName("Chris");
user.setLastName("Jones");
user.addRole(new Admin());
UserDAO dao = context.getBean("userDAO", UserDAO.class);
dao.persist(user);
System.out.println("Done");
}
编辑:在第一个答案之后,我在main方法中尝试了这个但得到了同样的例外:
Admin admin = new Admin();
admin.setId(1);
user.addRole(admin);
运行上述内容时,我的数据库中会创建两个名为USERS,ROLES和ADMINS的表。 USERS和ROLES / ADMINS之间似乎没有联系。我希望在USERS中有一个ROLE_ID(或ROLES中的USERNAME),但两者都没有。
这是堆栈跟踪。谢谢你的帮助。我很感激,一直试图解决这个问题!
Hibernate:
select
hibernate_sequence.nextval
from
dual
Hibernate:
insert
into
USERS
(PASSWORD, FIRST_NAME, LAST_NAME, USERNAME)
values
(?, ?, ?, ?)
Hibernate:
insert
into
ROLES
(ROLE_ID)
values
(?)
Hibernate:
insert
into
ADMINS
(ROLE_ID)
values
(?)
Hibernate:
update
ROLES
set
ROLE_ID=?
where
ROLE_ID=?
Exception in thread "main" javax.persistence.RollbackException: Error while commiting the transaction
at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:71)
at com.fdm.tradingplatform.dao.JPAManager.persist(JPAManager.java:21)
at com.fdm.tradingplatform.dao.UserDAO.persist(UserDAO.java:21)
at Main.main(Main.java:28)
Caused by: org.hibernate.exception.SQLGrammarException: Could not execute JDBC batch update
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:67)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:249)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:235)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:143)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:54)
... 3 more
Caused by: java.sql.BatchUpdateException: ORA-01722: invalid number
at oracle.jdbc.driver.DatabaseError.throwBatchUpdateException(DatabaseError.java:343)
at oracle.jdbc.driver.OraclePreparedStatement.executeBatch(OraclePreparedStatement.java:10768)
at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.executeBatch(NewProxyPreparedStatement.java:1723)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:48)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:242)
... 11 more
答案 0 :(得分:1)
此属性存在问题:
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name = "ROLE_ID")
private Set<Role> roles;
您尝试将角色的ID用作用户的外键。相反,Role
应该具有User
属性,您应该使用此属性来映射用户类中的角色。
在user
课程中添加Role
:
@Entity(name = "ROLES")
@Inheritance(strategy=InheritanceType.JOINED)
public abstract class Role implements Serializable{
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name = "ROLE_ID")
int id;
@ManyToOne
@JoinColumn(name = "USER_ID")
User user;
...
}
在User
类中,将角色集更改为:
@OneToMany(mappedBy = "user", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private Set<Role> roles;
答案 1 :(得分:0)
我认为问题是你正在制作一个新的Admin(),但不是坚持它。您需要保留它,以便它具有ID,以便您可以将其添加到用户。否则,您将一个空ID添加到int / long id字段,并且它会抛出该异常。