Search code examples
javaunit-testingjpajakarta-eeentitymanager

NullPointerException in dao layer (only persist is working)


I was looking for a similar problems, but no actual results, so I'm trying to create simple DAO layer with JPA/Maven, but if I use it then only persist method (insert) is working when I using EntityManager until class, but tests are working good if I create EntityManager with before and auto annotations without anything else. I'm getting NullPointerException, but I cannot understand why (especially why to persist method is working in this case).

Abstract test

public abstract class AbstractPersistentTest {

  protected static EntityManagerFactory emf = Persistence.createEntityManagerFactory("Services");
  protected EntityManager em;
  protected EntityTransaction tx;

  @Before
  public void initEntityManager() throws Exception {
    em = emf.createEntityManager();
    tx = em.getTransaction();
  }

  @After
  public void closeEntityManager() throws SQLException {
    if (em != null) em.close();
  }

  protected Integer getRandomId() {
    return Math.abs(new Random().nextInt());
  }
}

Model

@Entity
@Table(name = "test")
public class Test implements Serializable {

@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
@Column(name = "id")
private Integer id;

@Column(name = "title", nullable = false)
@Size(min = 0, max = 255)
private String title;

@Column(name = "descr", nullable = false, length = 16777215, columnDefinition = "Mediumtext")
private String descr;

@Column(name = "avatar", nullable = false)
private String avatar;

@Column(name = "date_add", nullable = false, insertable = false, updatable = false, columnDefinition = "Datetime DEFAULT CURRENT_TIMESTAMP")
@Temporal(TemporalType.TIMESTAMP)
private Date date_add;

public Test() {
}

//getters and setters

Test DAO

public class TestDAO  {

//@PersistenceContext(unitName = "Services")
//private EntityManager emgr;

public Integer persist(String title,
                       String avatar,
                       String descr) {

    EntityManager em = EMgrUtil.createEntityManager();
    EntityTransaction transaction = em.getTransaction();
    Test test = new Test();

    try {

        transaction.begin();
        test.setTitle(title);
        test.setAvatar(avatar);
        test.setDescr(descr);
        em.persist(test);
        transaction.commit();

    }
    catch(RuntimeException e) {
        e.printStackTrace();
        transaction.rollback();

    } finally {
        //em.close();
    }

    return test.getId();

}

public Test findById(Integer id) {

    EntityManager em = EMgrUtil.getEntityManager();
    Test t = em.find(Test.class, id);
    return t;

}

public List<Test> findAll() {

    EntityManager em = EMgrUtil.getEntityManager();

    List<Test> list = em.createQuery("SELECT t FROM Test t", Test.class).getResultList();

    return list;

}

}

I also trying to inject EntityManager via PersistenceContext but It doesn't work

main

public class testDAO_test {

    public static void main(String[] args) {

        TestDAO testDAO = new TestDAO();

        List<Test> tests = testDAO.findAll();

        for(Test test : tests) {
            System.out.println(test);
        }

        //Test test = testDAO.findById(2);
        //System.out.println(test);
    }

}

persistence.xml

<persistence xmlns="http://java.sun.com/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
             version="2.0">

    <persistence-unit name="Services" transaction-type="RESOURCE_LOCAL">
        <description>
            Maven Test JPA
        </description>
        <!--provider>org.hibernate.ejb.HibernatePersistence</provider-->
        <class>com.spring_test2.jpa.models.Test</class>

        <properties>
            <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
            <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/spring_test2" />
            <property name="javax.persistence.jdbc.user" value="root" />
            <property name="javax.persistence.jdbc.password" value="pwd" />
            <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/>

            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
            <property name="hibernate.show_sql" value="true" />
            <property name="hibernate.hbm2ddl.auto" value="update" />
        </properties>

    </persistence-unit>

</persistence>

Solution

  • Add null check for entity manager in getEntityManager() as you did in createEntityManager(), to create one em if it is null.

    Or simply use createEntityManager() instead of getEntityManager() in TestDAO for findAll() and findById() methods.