java Hibernate save单独成功,但如果运行时几乎没有其他测试,则会失败
我正在做一个项目,这是我在大学学习的一门课程中的一项作业。 在这个项目中,我们将在几次迭代中实现一个在线论坛系统。 这个迭代中的一个需求是使用ORM——我们选择了Hibernate,这是我们第一次体验它。到目前为止,我们过得很艰难:)
我们正在使用intelliJ Idea 14、windows、java 7、mysql 5和hibernate 4.2
在许多类中,我们有表示域层的POJO,有封装对DB的访问的hibernateUtils,还有一个用于测试它的Junit类
以下是带注释的POJO:
用户:
@Entity
@Table(name="user")
public class User {
@Id
@GeneratedValue
@Column(name="user_id")
private int id;
@Column(name="name")
private String username;
@Column(name="email_address")
private String emailAddress;
@Column(name="password")
private String hashedPassword;
@Column(name="date")
@Temporal(TemporalType.DATE)
private java.util.Date creationDate;
@OneToOne
@JoinColumn(name="state")
@Cascade({org.hibernate.annotations.CascadeType.ALL})
private UserState state;
@Column(name="is_active")
private boolean active;
@Column(name="is_banned")
private boolean banned;
@Column(name="is_logged_in")
private boolean loggedIn;
@ManyToMany
@Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE})
private Set<User> friends;
@OneToMany
@JoinColumn(name="panding_notfications")
@Cascade({org.hibernate.annotations.CascadeType.ALL})
private List<Notification> pendingNotifications;
@OneToMany( mappedBy = "receivingMember")
@Cascade({org.hibernate.annotations.CascadeType.ALL})
private List<FriendRequest> friendRequests;
@OneToMany( mappedBy = "reporter")
@Cascade({org.hibernate.annotations.CascadeType.ALL})
private List<Report> sentReports;
@Column(name="seniority")
private int seniority;
@Column(name="loginTime")
private long loginTime;
论坛:
@Entity
@Table(name="Forum")
public class Forum {
@Id
@GeneratedValue
@Column(name="forum_id", nullable = false, unique = true)
public int id;
@Column(name="name")
private String name;
@OneToOne
@JoinColumn(name = "admin")
@Cascade({org.hibernate.annotations.CascadeType.ALL})
private User admin;
@OneToMany
@JoinColumn(name="sub_forums")
@Cascade({org.hibernate.annotations.CascadeType.ALL})
private List<SubForum> subForums;
@OneToMany
@JoinColumn(name="members")
@Cascade({org.hibernate.annotations.CascadeType.ALL})
private List<User> members;
@OneToOne
@JoinColumn(name="policy")
@Cascade({org.hibernate.annotations.CascadeType.ALL})
private ForumPolicy policy;
冬眠:
public class HibernateUtils {
private static Configuration cfg;
private static SessionFactory sessionFactory =null;
public static boolean configure(boolean init) {
cfg = new Configuration()
.addAnnotatedClass(Forum.class)
.addAnnotatedClass(Message.class)
.addAnnotatedClass(SubForum.class)
.addAnnotatedClass(Thread.class)
.addAnnotatedClass(ForumPolicy.class)
.addAnnotatedClass(User.class)
.addAnnotatedClass(Report.class)
.addAnnotatedClass(Notification.class)
.addAnnotatedClass(FriendRequest.class)
.addAnnotatedClass(UserState.class)
.addAnnotatedClass(UserStatusPolicy.class)
.setProperty("hibernate.current_session_context_class","thread")
.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQLDialect")
.setProperty("hibernate.connection.driver_class","com.mysql.jdbc.Driver")
.setProperty("hibernate.connection.url","jdbc:mysql://localhost:3306/forum_system")
.setProperty("hibernate.connection.username","root")
.setProperty("hibernate.password", "");
if (init) {
cfg.setProperty("hibernate.hbm2ddl.auto", "create");
}
sessionFactory = cfg.configure().buildSessionFactory();
return cfg!=null;
}
public synchronized static boolean start() {
return configure(false);
}
public static boolean init() {
return configure(true);
}
public synchronized static boolean save(Object o) {
return saveReturnId(o) > 0;
}
public synchronized static int saveReturnId(Object o) {
Session session = sessionFactory.getCurrentSession();
try {
session.getTransaction().begin();
int id= (int)session.save(o);
session.getTransaction().commit();
return id;
}
catch(HibernateException e) {
System.out.println(e);
ForumLogger.errorLog(e.toString());
return -1;
}
finally{
if(session.isOpen()) {
session.close();
}
}
}
public synchronized static boolean del(Object o) {
Session session = sessionFactory.getCurrentSession();
try {
session.getTransaction().begin();
session.delete(o);
session.getTransaction().commit();
return true;
}
catch(HibernateException e) {
System.out.println(e);
ForumLogger.errorLog(e.toString());
return false;
}
finally{
if(session.isOpen()) {
session.close();
}
}
}
public synchronized static Object load(Class c,int id) {
Object o=null;
Session session = sessionFactory.getCurrentSession();
try {
session.getTransaction().begin();
o=session.get(c, id);
session.getTransaction().commit();
return o;
}
catch(HibernateException e) {
System.out.println(e);
ForumLogger.errorLog(e.toString());
return null;
}
finally{
if(session.isOpen()) {
session.close();
}
}
}
}
我们当前运行的测试类部分:
public class ForumTests {
@BeforeClass
public static void Setup() {
HibernateUtils.start();
}
@Test
public void testSaveForum() {
Forum f = new Forum(new User(),new ForumPolicy(),"forum_name");
int id = HibernateUtils.saveReturnId(f);
Assert.assertEquals(f, (Forum) HibernateUtils.load(Forum.class, id));
}
@Test
public void testGetAdmin() {
User u =User.newMember("asdsad","asd","sdkfdjk@sldkf.com");
Forum f = new Forum(u,new ForumPolicy(),"forum_name");
int fid = HibernateUtils.saveReturnId(f);
Forum ormf = (Forum) HibernateUtils.load(Forum.class, fid);
Assert.assertEquals(u, ormf.getAdmin());
}
@Test
public void testAddSubforumFromForum() {
User u =User.newMember("user","pass","mail@gmail.com");
int uid = (int)HibernateUtils.saveReturnId(u);
Assert.assertTrue(uid>0);
/* commented out code */
}
当分别运行以下每个测试时,它们都会成功。但是当运行所有这些测试时,我们会出现以下错误:(在testGetAdmin测试中)
May 27, 2015 2:11:43 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
WARN: SQL Error: 1452, SQLState: 23000
May 27, 2015 2:11:43 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
ERROR: Cannot add or update a child row: a foreign key constraint fails (`forum_system`.`forum`, CONSTRAINT `FK_l9pbqj2i36itiuhbu7q61xqlq` FOREIGN KEY (`admin`) REFERENCES `user` (`user_id`))
org.hibernate.exception.ConstraintViolationException: could not execute statement
我非常理解这一点,但我不明白为什么只有在一起运行所有测试时才会发生这种情况?(也许是关于交易的?)
谢谢:)
# 1 楼答案
您的测试是有状态的,也就是说,它们正在更改数据,并在运行后保持更改状态
这意味着当下一个测试运行时,数据不是“干净的”,而是被之前的测试污染了
要解决这个问题,请确保各个测试在运行后进行清理,或者在每个测试运行之前设置一个干净的环境——目前,您为整个类初始化了一次hibernate