-1

can you please explain me what i do wrong. I Am learning JPA and i'm stuck with tests. On the first test "teslaOne" i create and persist Entity to the db and i would like to get access to this data from second test "teslaTwo".

When i use Persistence.createEntityManagerFactory("h2database") it works but when i store it on the memoty Persistence.createEntityManagerFactory("in.memory.test") it does not.

i understand that "h2database" it is a fila, "in.memory.test" memory but it not clear for me why it have a different behavior and why it nullify data.

Can you tell me please how to share EntityManager between tests.

persistence.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<persistence xmlns="https://jakarta.ee/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             version="3.0"
             xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd">
    <persistence-unit name="h2database" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <class>com.caveatemptor.core.data.entites.Tesla</class>
        <exclude-unlisted-classes>false</exclude-unlisted-classes>

        <properties>
            <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
            <property name="hibernate.hbm2ddl.auto" value="update"/>
            <property name="hibernate.connection.driver_class" value="org.h2.Driver"/>
            <property name="hibernate.connection.username" value="sa"/>
            <property name="hibernate.connection.password" value=""/>
            <property name="hibernate.connection.url" value="jdbc:h2:file:./h2data/demodb"/>
            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.format_sql" value="true"/>

        </properties>
    </persistence-unit>

    <persistence-unit name="in.memory.test" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <class>com.caveatemptor.core.data.entites.Tesla</class>

        <exclude-unlisted-classes>false</exclude-unlisted-classes>

        <properties>
            <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
            <property name="hibernate.hbm2ddl.auto" value="update"/>
            <property name="hibernate.connection.driver_class" value="org.h2.Driver"/>
            <property name="hibernate.connection.url" value="jdbc:h2:mem:"/>
            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.format_sql" value="false"/>
        </properties>
    </persistence-unit>

</persistence>

Tesla.java

@Setter
@Getter
@ToString
@Entity()
public class Tesla implements Serializable {
    @Id
    @GeneratedValue
    protected Long ID;

    protected String vehicle;
}

TeslaTest.java

package com.caveatemptor.core.data.inheritance;

import com.caveatemptor.core.data.entites.Tesla;
import jakarta.persistence.*;
import org.junit.jupiter.api.Test;

import java.util.List;

import static org.junit.jupiter.api.Assertions.assertEquals;

public class TeslaTest {
//    private final EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("h2database");
    private final EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("in.memory.test");
    @Test
    void teslaOne(){
        Tesla tesla = new Tesla();
        tesla.setVehicle("Model X");

        EntityManager entityManager = entityManagerFactory.createEntityManager();

        EntityTransaction transaction = entityManager.getTransaction();

        try {
            transaction.begin();

            entityManager.persist(tesla);
            transaction.commit();

            Tesla teslaV = entityManager.find(Tesla.class, tesla.getID());
            assertEquals(teslaV.getVehicle(), "Model X");

        }
        finally {
            if(transaction.isActive()){
                transaction.rollback();
            }
            entityManager.close();
        }
    }


    @Test
    void teslaTwo(){
        EntityManager entityManager = entityManagerFactory.createEntityManager();

        EntityTransaction transaction = entityManager.getTransaction();

        try {
            transaction.begin();

            TypedQuery<Tesla> query = entityManager.createQuery("select t from Tesla t", Tesla.class);
            List<Tesla> items = query.getResultList();
            assertEquals(1, items.size());
        }
        finally {
            if(transaction.isActive()){
                transaction.rollback();
            }
            entityManager.close();
        }
    }

}

Romillion
  • 101
  • 1
  • 3
  • It’s been a bit since I worked with JUnit so I’m not 100% sure this will work, but you can declare your `EntityManager` as an instance variable and instantiate it in a setup method with the `@BeforeAll` annotation. – Calvin P. Feb 25 '23 at 02:47

1 Answers1

0

It makes sense that it’s not keeping the same in memory database as, without really knowing much about it, I assume it works much the same as objects and is stored in the heap. When you call createEntityManager() the second time, it’s like creating a new object and the reference points to the new object, leaving the old one to get cleaned up by the GarbageCollector.

To prevent having to initialize the in memory database a second time, I believe setting it up as a @BeforeAll should do the trick.

private final EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("in.memory.test");
private EntityManager entityManager;

@BeforeAll
void setup() {
    entityManager = entityManagerFactory.createEntityManager();
}
Calvin P.
  • 1,116
  • 2
  • 8
  • 13