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();
// ...
}
}
- Is it enough making add(), delete(), update() and getAll() methods synchronized?
- Can I create multiple instances of DbService like in my source? Or do I need to create only one instance?
- Maybe I should to use the singleton design pattern? Or make DbService static with all methods?
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 makeem
static. Singleton would be my preference. You also don't wantem
be public. Make it private while you are at it.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