有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

  1. # 1 楼答案

    您的测试是有状态的,也就是说,它们正在更改数据,并在运行后保持更改状态

    这意味着当下一个测试运行时,数据不是“干净的”,而是被之前的测试污染了

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