1

I am trying to figure out what benefits does the @Repository annotation provides. I understand that @Component ,@Service ,@Repository are basically stereotype annotation that are mainly used for segregating the layers and applying the AOP pointcuts. The only thing I found out that @repository provides automatic exception translation. My question is how? I implemented the below dao class using JDBC template and H2 Database :

@Repository
public class UserDaoImpl implements UserDao {
    @Autowired
    JdbcTemplate jdbcTemplate;

    public void saveUser(Users user) {
        try {
            jdbcTemplate.update("insert into users(name,address,age) values (?,?,?)",
                    new Object[] { user.getName(), user.getAddress(), null });
        } catch (DataAccessException e) {
            e.printStackTrace();
        }
    }

}

The entity class is :

@Entity
public class Users {

    @Column(name = "name", nullable = true)
    private String name;

    @Column(name = "address", nullable = true)
    private String address;

    @Column(name = "age", nullable = false)
    private Integer age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

}

There is a not null constraint on "age" column in DB. I was expecting the exception as DataAccessException wrapped object in case I use @Repository and normal H2 DB exception if I use @component or @service. But its not happening. It's showing the same excpetion trace no matter what annotation I use.

org.springframework.dao.DataIntegrityViolationException: PreparedStatementCallback; SQL [insert into users(name,address,age) values (?,?,?)]; integrity constraint violation: NOT NULL check constraint; SYS_CT_10092 table: USERS column: AGE; nested exception is java.sql.SQLIntegrityConstraintViolationException: integrity constraint violation: NOT NULL check constraint; SYS_CT_10092 table: USERS column: AGE
    at org.springframework.jdbc.support.SQLExceptionSubclassTranslator.doTranslate(SQLExceptionSubclassTranslator.java:87)
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)
    at org.springframework.jdbc.core.JdbcTemplate.translateException(JdbcTemplate.java:1414)
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:632)
    at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:862)
    at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:917)
    at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:927)
    at com.spring.practice.dao.daoimpl.UserDaoImpl.saveUser(UserDaoImpl.java:18)
    at com.spring.practice.service.serviceimpl.UserServiceImpl.saveUser(UserServiceImpl.java:38)
    at com.spring.practice.main.MainClass.main(MainClass.java:14)
Caused by: java.sql.SQLIntegrityConstraintViolationException: integrity constraint violation: NOT NULL check constraint; SYS_CT_10092 table: USERS column: AGE
    at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source)
    at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source)
    at org.hsqldb.jdbc.JDBCPreparedStatement.fetchResult(Unknown Source)
    at org.hsqldb.jdbc.JDBCPreparedStatement.executeUpdate(Unknown Source)
    at org.springframework.jdbc.core.JdbcTemplate.lambda$update$0(JdbcTemplate.java:867)
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:617)
    ... 6 more
Caused by: org.hsqldb.HsqlException: integrity constraint violation: NOT NULL check constraint; SYS_CT_10092 table: USERS column: AGE

So my only confusion is that what benefits does @repository provide?

Thanks in advance.

New Bee
  • 1,007
  • 4
  • 18
  • 34
  • Can you post your `User` domain class? – Avijit Barua Nov 13 '18 at 08:16
  • @AvijitBarua Just updated – New Bee Nov 13 '18 at 08:21
  • Just in case you have not seen this answer: https://stackoverflow.com/a/38549461/2021763. Raman Sahasi talks about the PersistenceExceptionTranslationPostProcessor, which you seem to mention, but not explicitly. If this is true, it might be useful to rephrase your question and mention the PersistenceExceptionTranslationPostProcessor. Because I think your actual question is: "When does the PersistenceExceptionTranslationPostProcessor becomes active?" – gillesB Nov 13 '18 at 08:30
  • @NewBee Can you please check my answer ! – Avijit Barua Nov 13 '18 at 08:37
  • 1
    @gillesB yes you are right. Ill go through the mentioned post. I was just checking why annotating my dao with Component annotation also shows the exact stacktrace as Repository annotation. I am trying to figure out what I am missing here. – New Bee Nov 13 '18 at 08:54

1 Answers1

2

I found the answer. I was getting the same exception trace in both cause because I was using JDBCTemplate. JDBCTemplate internally handles this task so in any case u'll get the same exception trace. I used hibernate instead of JDBC template and the exception trace is as expected. PFB the trace :

With Component annotation :

Exception in thread "main" org.hibernate.HibernateException: No Session found for current thread
    at org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:106)
    at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:1014)
    at com.spring.practice.dao.daoimpl.UserDaoImpl.saveUser(UserDaoImpl.java:25)
    at com.spring.practice.service.serviceimpl.UserServiceImpl.saveUser(UserServiceImpl.java:38)
    at com.spring.practice.main.MainClass.main(MainClass.java:14)

With Repository annotation (Exception translation to spring exception) :

Exception in thread "main" org.springframework.orm.hibernate4.HibernateSystemException: No Session found for current thread; nested exception is org.hibernate.HibernateException: No Session found for current thread
    at org.springframework.orm.hibernate4.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:216)
    at org.springframework.orm.hibernate4.HibernateExceptionTranslator.convertHibernateAccessException(HibernateExceptionTranslator.java:57)
    at org.springframework.orm.hibernate4.HibernateExceptionTranslator.translateExceptionIfPossible(HibernateExceptionTranslator.java:44)
    at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:59)
    at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:147)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
    at com.sun.proxy.$Proxy16.saveUser(Unknown Source)
    at com.spring.practice.service.serviceimpl.UserServiceImpl.saveUser(UserServiceImpl.java:38)
    at com.spring.practice.main.MainClass.main(MainClass.java:14)
Caused by: org.hibernate.HibernateException: No Session found for current thread
    at org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:106)
    at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:1014)
    at com.spring.practice.dao.daoimpl.UserDaoImpl.saveUser(UserDaoImpl.java:25)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
    ... 5 more

This translation will never happen in case of jdbcTemplate as its internally handled by jdbcTemplate. So we do not need PersistenceExceptionTranslationPostProcessor in case of jdbcTemplate.

New Bee
  • 1,007
  • 4
  • 18
  • 34