问题
I have written this service class for database CRUD operations.
visible public class CompanyServiceImpl extends PersistentRemoteService implements CompanyService {
private GileadHibernateUtil gileadHibernateUtil;
public CompanyServiceImpl() {
gileadHibernateUtil = new GileadHibernateUtil();
setBeanManager(gileadHibernateUtil.getPersistentBeanManager());
}
@Override
public void addCompany(Company newCompany) {
Objects.requireNonNull(newCompany, "newCompany is null.");
Session session = gileadHibernateUtil.getCurrentSession();
Transaction transaction = null;
try {
transaction = session.beginTransaction();
session.persist(newCompany);
session.getTransaction().commit();
} finally {
if (transaction.isActive()) {
transaction.rollback();
}
session.close();
}
}
@Override
public Company updateCompany(Company company) {
Objects.requireNonNull(company, "company is null.");
Session session = gileadHibernateUtil.getCurrentSession();
Transaction transaction = null;
Company managedCompany = null;
try {
transaction = session.beginTransaction();
managedCompany = (Company) session.merge(company);
session.getTransaction().commit();
} finally {
if (transaction.isActive()) {
transaction.rollback();
}
}
return managedCompany;
}
@Override
public void deleteCompany(Company company) {
Objects.requireNonNull(company, "company is null.");
Session session = gileadHibernateUtil.getCurrentSession();
Transaction transaction = null;
try {
transaction = session.beginTransaction();
session.delete(company);
session.getTransaction().commit();
} finally {
if (transaction.isActive()) {
transaction.rollback();
}
}
}
@Override
public Company findCompany(int companyId) {
if (companyId <= 0) {
throw new IllegalArgumentException("companyId must be a positive integer.");
}
Session session = gileadHibernateUtil.getCurrentSession();
Transaction transaction = null;
Company company = null;
try {
transaction = session.beginTransaction();
company = (Company) session.get(Company.class, companyId);
session.getTransaction().commit();
} finally {
if (transaction.isActive()) {
transaction.rollback();
}
}
return company;
}
@Override
public List<Company> findMatchingCompanies(String companyName) {
Session session = gileadHibernateUtil.getCurrentSession();
Transaction transaction = null;
List<Company> matchingCompanies = null;
try {
transaction = session.beginTransaction();
Criteria searchCriteria = session.createCriteria(Company.class).add(
Restrictions.or(Restrictions.like("code", companyName), Restrictions.like("name", companyName)));
session.getTransaction().commit();
matchingCompanies = searchCriteria.list();
} finally {
if (transaction.isActive()) {
transaction.rollback();
}
}
return matchingCompanies;
}
@Override
public List<Company> findAllCompanies() {
Session session = gileadHibernateUtil.getCurrentSession();
Transaction transaction = null;
List<Company> companies = null;
try {
transaction = session.beginTransaction();
Criteria searchCriteria = session.createCriteria(Company.class);
session.getTransaction().commit();
companies = searchCriteria.list();
} finally {
if (transaction.isActive()) {
transaction.rollback();
}
}
return companies;
}
}
I decided to not use a separate DAO layer. Its a small app and I am not going to switch from Hibernate. All it would have included was Hibernate session commands. Beginning and ending a transaction still comes in business layer. So, Hibernate pretty much works as the DAO layer for me. What's pinching me is the seemingly boilerplate code for transactions, which has to be written in every CRUD method. Is this any better way, or is this the minimum amount of code that is going to be repeated no matter what?
回答1:
If you are using spring and are able to use annotations. There is a good article on the link provided which shows how to use annotations to wrap a method in a transaction.
http://springinpractice.com/2008/03/18/annotation-based-transactions-in-spring/
using spring and hibernate together would make your code look cleaner and would look something like what is below.
@Override
@Transactional
public void addCompany(Company newCompany) {
Objects.requireNonNull(newCompany, "newCompany is null.");
Session session = gileadHibernateUtil.getCurrentSession();
session.persist(newCompany);
//session.close(); this line would also not be needed because the session would close automatically when the transaction is complete.
}
回答2:
Without spring something like this can be done using
java.util.function.Function
public static Object transactionExecutor(Function<Session, Object> toRun) {
Session session = null;
Object result = null;
try {
session = getSession();
final Transaction tx = session.beginTransaction();
result = toRun.apply(session);
session.flush();
tx.commit();
return result;
} catch (HibernateException he) {
Transaction tx = session.getTransaction();
tx.rollback();
} finally {
session.close();
}
return result;
}
public static void save(final Students S) {
Function<Session, Object> toRun = new Function<Session, Object>() {
@Override
public Object apply(final Session t) {
t.save(S);
return S.getId();
}
};
int saveID = (int)transactionExecutor(toRun);
}
来源:https://stackoverflow.com/questions/14566701/hibernate-boilerplate-code-for-transactions