java 中的异常:如何减少重复代码
Exceptions in java: how reduce repeated code
我在 Java 中使用数据访问对象 (DAO) 模式,并且在我的所有文件中重复了相同的代码段。事情是这样的:
public User getById(int id) throws BDException {
Session session = sessionFactory.getCurrentSession();
Transaction tx = session.getTransaction();
try {
tx.begin();
Query query = session.createQuery("SELECT u FROM User u WHERE u.id=:id");
query.setString("id", id);
User user = (User) query.uniqueResult();
tx.commit();
return user;
}
catch(javax.validation.ConstraintViolationException | org.hibernate.exception.ConstraintViolationException cve) {
try {
if(tx.getStatus() == TransactionStatus.ACTIVE) {
tx.rollback();
}
}
catch(Exception exc) {
LOGGER.error("Error rollback in method='" + getMethodName() + "'");
}
throw new BDException(cve);
}
catch(RuntimeException ex) {
try {
if(tx.getStatus() == TransactionStatus.ACTIVE) {
tx.rollback();
}
}
catch(Exception exc) {
LOGGER.error("Error rollback in method='" + getMethodName() + "'");
}
throw ex;
}
catch(Exception ex) {
try {
if(tx.getStatus() == TransactionStatus.ACTIVE) {
tx.rollback();
}
}
catch(Exception exc) {
LOGGER.error("Error rollback in method='" + getMethodName() + "'");
}
throw new RuntimeException(ex);
}
}
好吧,我想让你看看关键部分。我用我拥有的每一种方法都重复了它。如果它是简单的代码,我可以创建一个方法,将所有代码放入其中并调用该方法,而不是重复代码。问题是它不是正常代码,它们是异常。
那么,有什么解决方案可以重用代码,而不是在每个方法中重复(复制粘贴)代码吗?
谢谢!
is there any solution to reuse code and not to repeat (copy-pasting) the code in every method?
有。
你的函数"meat"在这里
Query query = session.createQuery("SELECT u FROM User u WHERE u.id=:id");
query.setString("id", id);
User user = (User) query.uniqueResult();
如果你仔细观察,你可能会发现这是一个接受 Session
作为参数的 "function",而 returns 是一个 User
。然后你可以做的是让这个函数成为执行所有异常处理的东西的参数。
在 Java 中,这通常意味着将函数表示为 "object"
User MyCrazyFunctionThing::uniqueResult(Session session) {
Query query = session.createQuery(this.sql);
query.setString("id", this.id);
return query.uniqueResult();
}
User DatabaseGateway::execute(MyCrazyFunctionThing q) {
Session session = sessionFactory.getCurrentSession();
Transaction tx = session.getTransaction();
try {
tx.begin();
User user = q.uniqueResult(session)
tx.commit();
return user;
} catch (...) {
// ...
}
}
立即,您可以将其转化为逻辑,可以是 运行 任何时候您尝试从会话中获取唯一用户时的逻辑。
您可以使用泛型使其更加通用
interface MyCrazyGenericThing<T> {
T uniqueResult(Session session);
}
class MyCrazyFunctionThing implements MyCrazyGenericThing<User> {
User uniqueResult(Session session) {
Query query = session.createQuery(this.sql);
query.setString("id", this.id);
return query.uniqueResult();
}
}
<T> T DatabaseGateway::execute(MyCrazyGenericThing<T> q) {
Session session = sessionFactory.getCurrentSession();
Transaction tx = session.getTransaction();
try {
tx.begin();
T result = q.uniqueResult(session)
tx.commit();
return result;
} catch (...) {
// ...
}
}
您在这里看到的是策略模式,用于指定事务逻辑中应该 运行 的代码。
看起来像是 Execute Around idiom 的工作。
将专用代码放在 lambda 表达式中。将专用代码传递给具有通用代码的方法,该方法在适当的点执行持有 lambda 表达式的对象。
对于您的代码,具体取决于您要分解的内容,用法可能类似于:
public User getById(int id) throws BDException {
return query(
"SELECT u FROM User u WHERE u.id=:id",
query -> {
query.setString("id", id);
return (User) query.uniqueResult();
}
);
}
我在 Java 中使用数据访问对象 (DAO) 模式,并且在我的所有文件中重复了相同的代码段。事情是这样的:
public User getById(int id) throws BDException {
Session session = sessionFactory.getCurrentSession();
Transaction tx = session.getTransaction();
try {
tx.begin();
Query query = session.createQuery("SELECT u FROM User u WHERE u.id=:id");
query.setString("id", id);
User user = (User) query.uniqueResult();
tx.commit();
return user;
}
catch(javax.validation.ConstraintViolationException | org.hibernate.exception.ConstraintViolationException cve) {
try {
if(tx.getStatus() == TransactionStatus.ACTIVE) {
tx.rollback();
}
}
catch(Exception exc) {
LOGGER.error("Error rollback in method='" + getMethodName() + "'");
}
throw new BDException(cve);
}
catch(RuntimeException ex) {
try {
if(tx.getStatus() == TransactionStatus.ACTIVE) {
tx.rollback();
}
}
catch(Exception exc) {
LOGGER.error("Error rollback in method='" + getMethodName() + "'");
}
throw ex;
}
catch(Exception ex) {
try {
if(tx.getStatus() == TransactionStatus.ACTIVE) {
tx.rollback();
}
}
catch(Exception exc) {
LOGGER.error("Error rollback in method='" + getMethodName() + "'");
}
throw new RuntimeException(ex);
}
}
好吧,我想让你看看关键部分。我用我拥有的每一种方法都重复了它。如果它是简单的代码,我可以创建一个方法,将所有代码放入其中并调用该方法,而不是重复代码。问题是它不是正常代码,它们是异常。
那么,有什么解决方案可以重用代码,而不是在每个方法中重复(复制粘贴)代码吗?
谢谢!
is there any solution to reuse code and not to repeat (copy-pasting) the code in every method?
有。
你的函数"meat"在这里
Query query = session.createQuery("SELECT u FROM User u WHERE u.id=:id");
query.setString("id", id);
User user = (User) query.uniqueResult();
如果你仔细观察,你可能会发现这是一个接受 Session
作为参数的 "function",而 returns 是一个 User
。然后你可以做的是让这个函数成为执行所有异常处理的东西的参数。
在 Java 中,这通常意味着将函数表示为 "object"
User MyCrazyFunctionThing::uniqueResult(Session session) {
Query query = session.createQuery(this.sql);
query.setString("id", this.id);
return query.uniqueResult();
}
User DatabaseGateway::execute(MyCrazyFunctionThing q) {
Session session = sessionFactory.getCurrentSession();
Transaction tx = session.getTransaction();
try {
tx.begin();
User user = q.uniqueResult(session)
tx.commit();
return user;
} catch (...) {
// ...
}
}
立即,您可以将其转化为逻辑,可以是 运行 任何时候您尝试从会话中获取唯一用户时的逻辑。
您可以使用泛型使其更加通用
interface MyCrazyGenericThing<T> {
T uniqueResult(Session session);
}
class MyCrazyFunctionThing implements MyCrazyGenericThing<User> {
User uniqueResult(Session session) {
Query query = session.createQuery(this.sql);
query.setString("id", this.id);
return query.uniqueResult();
}
}
<T> T DatabaseGateway::execute(MyCrazyGenericThing<T> q) {
Session session = sessionFactory.getCurrentSession();
Transaction tx = session.getTransaction();
try {
tx.begin();
T result = q.uniqueResult(session)
tx.commit();
return result;
} catch (...) {
// ...
}
}
您在这里看到的是策略模式,用于指定事务逻辑中应该 运行 的代码。
看起来像是 Execute Around idiom 的工作。
将专用代码放在 lambda 表达式中。将专用代码传递给具有通用代码的方法,该方法在适当的点执行持有 lambda 表达式的对象。
对于您的代码,具体取决于您要分解的内容,用法可能类似于:
public User getById(int id) throws BDException {
return query(
"SELECT u FROM User u WHERE u.id=:id",
query -> {
query.setString("id", id);
return (User) query.uniqueResult();
}
);
}