Bem, o que você está fazendo não é avançado, é errado.
Você deve ter um persistence manager aberto pra cada requisição que tiver que ser tratada, você não deve abrir um único pesistence manager pra toda a aplicação e ficar sincronizando ele.
Já pensou no caso de ele lançar uma exceção?
A partir do momento que o seu persistence manager lançar uma exceção ele fica inútilizado, então a sua aplicação simplesmente pararia de funcionar pra todo mundo porque aconteceu um erro com apenas uma requisição.
Nesse primeiro momento, como você ainda não tem muito conhecimento (nem muita preocupação) com demarcação de transações e coisas do gênero (na maior parte das aplicações você nem se preocupa com isso) cada um dos métodos do seu DAO deveriam abrir um persistence manager e iniciar uma transação só pra eles, não esquecendo de fechar o persistence manager ao fim de cada método.
Outra coisa, o que você chama de “demora pra abrir uma única conexão” é na verdade a demora pra criar um persistence manager factory que é um criador de conexões e aonde as configurações do JPA ficam guardadas, no contrutor do seu dao você sempre faz isso:
factory = Persistence.createEntityManagerFactory("TerminalWebPU");
Quando na verdade essa criação deveria estar em um bloco estático fora do construtor do seu DAO. O seu dao provavelmente ficaria assim:
public class BaseDao {
static EntityManagerFactory factory = Persistence.createEntityManagerFactory("TerminalWebPU");
EntityManager manager;
public BaseDao() throws Exception {
manager = factory.createEntityManager();
}
public List<? extends Object> search(String qryName, Object... arg) throws DatabaseException {
Query query = manager.createNamedQuery(qryName);
for (int i = 0; i < arg.length; i += 2) {
String name = (String) arg[i];
if (arg[i + 1] instanceof String) {
query.setParameter(name, (String) arg[i + 1]);
} else {
if (arg[i + 1] instanceof Integer) {
query.setParameter(name, arg[i + 1]);
} else {
if (arg[i + 1] instanceof Date) {
query.setParameter(name, arg[i + 1]);
} else {
if (arg[i + 1] instanceof Boolean) {
query.setParameter(name, arg[i + 1]);
}
}
}
}
}
return query.getResultList();
}
public Boolean persistObject(Object obj) {
EntityTransaction transaction = manager.getTransaction();
try {
transaction.begin();
manager.persist(obj);
transaction.commit();
return true;
} catch (Exception e) {
transaction.rollback();
e.printStackTrace();
return false;
}
}
public Boolean removeObject(Object obj) {
EntityTransaction transaction = manager.getTransaction();
try {
transaction.begin();
manager.remove(obj);
transaction.commit();
return true;
} catch (Exception e) {
transaction.rollback();
e.printStackTrace();
return false;
}
}
public Object searchId(Class clas, Object pk) {
Object result = manager.find(clas, pk);
return result;
}
}
E como o Sérgio já bem disse, não use synchronized sem saber exatamente o que é que você está fazendo e quais vão ser os resultados dessa ação. Se você está com penas dois meses de Java, aproveite um pouco mais o seu tempo pra entender da linguagem e menos de receitas de bolo.
É claro que é chato ficar brincnado com console, swing e essas coisas, mas simplesmente pular pra aplicações web e ainda mais usando JPA sem entender como as coisas funcionam é perigoso, além de ser ruim pra você, que pode pegar maus costumes por não ter sido “apresentado” a maneiras melhores de se resolver o problema.