'Spring boot transform code to @Transactional

im new Spring. I trying to create my application, but have problems with design Repository class. In my realization i opening and closing session in every Repository methods. And in delete method i initiate transaction, because without this, the changes are not reflected in the database (H2) data structure. I don't like this realization and trying to transform it to @Transaction, but it not work.

Here is my code:

// Repository

@Repository("SampleRepository")
public class SampleRepository implements SampleDao {

    private static final Log log = LogFactory.getLog(SampleRepository.class);

    @Autowired
    private SessionFactory sessionFactory;

    private Session session;

    @Override
    public void save(SampleEntity sampleEntity) {
        Session session = sessionFactory.openSession();
        Serializable insertedId = session.save(sampleEntity);
        log.info("Added new row to Sample table with id: " + insertedId.toString());
        session.close();
    }

    @Override
    public void delete(SampleEntity sampleEntity) {
        Session session = sessionFactory.openSession();
        session.beginTransaction();
        session.delete(sampleEntity);
        session.getTransaction().commit();
        log.info("Deleted row " + sampleEntity.getId() + " from Sample table");
        session.close();
    }

    @Override
    public List<SampleEntity> findAll() {
        Session session = sessionFactory.openSession();
        CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
        CriteriaQuery<SampleEntity> criteriaQuery = 
        criteriaBuilder.createQuery(SampleEntity.class);
        Root<SampleEntity> rootEntry = criteriaQuery.from(SampleEntity.class);
        CriteriaQuery<SampleEntity> all = criteriaQuery.select(rootEntry);

        TypedQuery<SampleEntity> allQuery = session.createQuery(all);
        List<SampleEntity> resultList = allQuery.getResultList();
        session.close();
        return resultList;
    }

}

// Sample DAO

public interface SampleDao {
    List<SampleEntity> findAll();
    void save(SampleEntity sampleEntity);
    void delete(SampleEntity sampleEntity);
}

// Entity

@Entity
@Table(name = "Sample")
public class SampleEntity implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    @Column(name = "test1")
    private String test1;

    @Column(name = "test2")
    private String test2;

    @Column(name = "test3")
    private String test3;

    public void setTest1(String text) { this.test1 = text; }

    public void setTest1(String text) { this.test2 = text; }

    public void setTest1(String text) { this.test3 = text; }

}

// Component

@Component
public class SampleComponent {
    
    @Autowired
    private SampleRepository sampleRepository;

    private SampleEntity sampleEntity; 

    public void addFindAndDeleteSample() {

       sampleEntity = new SampleEntity();
       sampleEntity.setTest1("Test 1");
       sampleEntity.setTest2("Test 2");
       sampleEntity.setTest3("Test 3");

       sampleRepository.save(sampleEntity);

       List<SampleEntity> sampleEntityList = sampleRepository.findAll();

       for (SampleEntity sampleEntity : sampleEntityList) {
          try {
            sampleRepository.delete(sampleEntity);
          } catch (Exception ex) {
            System.out.println(ex.getMessage());
          }
       }
    }
}

Question is: how to design a repository so that it works through transactions and in each method it would not be necessary to open and close a session?



Solution 1:[1]

Have a look at CrudRepository or JpaRepository. By creating an interface of your own, which extends one of these, spring will inject an implementation of a repository which has a set of pre-defined methods. This way you don't need to implement it yourself.

Each of those methods are inside a transaction already, so no need to ad @Transactional on the methods just for simple actions such as findById(T id) or save(T entity). @Transactional should be used in cases where you want to include more changes before the commit should take place.

add interface class:

public interface SampleEntityRepository extends CrudRepository<SampleEntity, Long> {}

change autowire to inject the SampleEntityRepository instead of your own implemented SampleRepository.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 tbjorch