How to make DB access with Hibernate JPA thread-sa

2020-08-01 05:02发布

问题:

I would like to know what I need to do in order to make the access to DB thread-safe.

This is my Entity class:

@Entity
@Table(name = "students")
@NamedQuery(name = "Student.getAll", query = "SELECT s FROM Student s")
public class Student {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    @Column(length = 32, name = "name")
    private String name;

    // ... constructor, getters and setters, toString ...
}

This is the DbService class:

public class DbService {

    public EntityManager em = Persistence
                         .createEntityManagerFactory("MyPersistenceUnit")
                         .createEntityManager();

    public Student add(Student student) {
        EntityTransaction tx = em.getTransaction();
        tx.begin();
        Student studentFromDb = em.merge(student);
        tx.commit();
        return studentFromDb;
    }

    public void delete(long id) {
        EntityTransaction tx = em.getTransaction();
        tx.begin();
        em.remove(get(id));
        tx.commit();
    }

    public Student get(long id) {
        return em.find(Student.class, id);
    }

    public void update(Student student) {
        EntityTransaction tx = em.getTransaction();
        tx.begin();
        em.merge(student);
        tx.commit();
    }

    public List<Student> getAll() {
        TypedQuery<Student> namedQuery =
                     em.createNamedQuery("Student.getAll", Student.class);
        return namedQuery.getResultList();
    }

}

And here is a class that work with DbService:

public class SomeDbWorker implements Runnable {
    @Override
    public void run() {
        DbService service = new DbService();

        // do something ...
        service.add( ... );
        service.delete( ... );
        service.getAll();
        // ...
    }
}

  1. Is it enough making add(), delete(), update() and getAll() methods synchronized?
  2. Can I create multiple instances of DbService like in my source? Or do I need to create only one instance?
  3. Maybe I should to use the singleton design pattern? Or make DbService static with all methods?

回答1:

No need to synchronize anything,

the entityManager is not threadSafe and designed to be instantiated for each unit of work and destroyed just after.

The factory on the contrary is costly to create and should be reused

See http://docs.oracle.com/javaee/6/tutorial/doc/bnbqw.html "Application-Managed Entity Managers" and https://stackoverflow.com/a/22773758/2087640



回答2:

You don't need to make those methods synchronized, they are thread safe as it is. Yeah, it probably makes sense to make DbService a singleton. Alternatively, you could just make em static. Singleton would be my preference. You also don't want em be public. Make it private while you are at it.