# Migrating from Developing Asynchronous Multi-Threading Programs to Reactive Programs in Java
## 6 Implementation Details
### Database Interactions  
The asynchronous solution relies on a blocking model for database access but benefits from a full mapping of Java classes to the database structures, thanks to a comprehensive set of functionalities provided by Hibernate and JPA [55]. The database schema initialization happens automatically at runtime once the application is launched, based exclusively on metadata extracted from annotations. The integration with Hibernate allows the automatic generation of unique identifiers for each entity, e.g., annotating the _id_ field of the _TweetEntity_ with _@GeneratedValue_, and the definition and management of data relationships, including those made using link tables by specifying association columns. In this example, the relationships between messages, mentions, and tags tables are defined using the _@OneToMany_, _@ManyToMany_, _@JoinTable_, and _@JoinColumn_ annotations. In addition, data integrity is ensured thanks to support for cascading operations, but also the automatic removal of entities whose parent is deleted, achieved in this scenario by specifying _CascadeType_.ALL_ and enabling _orphan Removal_ for mentions and tags. Implementing database access and performing CRUD (Create, Read, Update, Delete) operations for managed entities is achieved by defining repositories that extend the _JpaRepository_ interface, considerably simplifying the integration and manipulation process. By providing an extensive suite of predefined methods and the ability to define additional queries by simply respecting a method naming convention, e.g., the repository method _findByTweetIdOrderByCreatedAtDesc_ which allows for retrieval of message replies in descending order by their creation date, the functionality available in the asynchronous model through the integration with JPA enables quick and efficient access to stored data, including the ability to execute queries of considerable complexity. The definition of native queries allows direct use of SQL syntax, providing complete control over execution beyond the abstraction provided by the framework, which may allow certain scenarios to adjust and optimize the behavior as well as to use particular functionalities specific to the database system. In the previous example, a native query was defined as the _searchUsers_ method to look up users by their names in a case-insensitive way. Last but not least, JPQL queries, such as the one defined to retrieve the top reply of a message by calling the method _findTopReplyByLikesForTweetId_, allow for the extraction of information from entities directly in the desired format through direct access to public model class constructors, and functionalities such as paging and _EntityGraph_, which were employed to eagerly fetch the tags and mentions only in this scenario since they were always required, provide granular control over loading strategies and efficient data access management. Listing 2 includes a subset of methods and queries that were used in the asynchronous implementation in addition to the predefined ones. **Listing 2**. Examples of methods for database access in asynchronous applications.