Hibernate保存单独成功但如果少量其他测试运行则会失败

时间:2015-05-27 11:51:00

标签: java mysql hibernate

我正在开展一个项目,这是我在大学就读的课程。 在这个项目中,我们将在几次迭代中实现一个在线论坛系统。 这次迭代的一个要求就是使用ORM - 我们选择了Hibernate,这是我们第一次体验它。到目前为止,我们度过了一段艰难时期:)

我们正在使用intelliJ Idea 14,windows,java 7,mysql 5和hibernate 4.2。

在许多类中,我们有POJO代表域层,我们有hibernateUtils封装了对DB的访问,还有一个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;

HibernateUtils:

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 个答案:

答案 0 :(得分:0)

您的测试是有状态的,即他们正在更改数据并在运行后将其更改。

这意味着当下一次测试运行时,数据不会干净&#34;但是之前的测试一直很困扰。

要解决此问题,请确保各个测试自行清理或在每次测试运行之前设置一个干净的环境 - 目前您为整个类初始化一次hibernate