JDBC, JPA, Hibernate
Spring with JDBC
@Repository
class PersonJdbcDao {
@Autowired
JdbcTemplate template;
public List<Person> findAll() {
return template.query("select * from person",
new BeanPropertyRowMapper(Person.class));
}
}
Spring with JPA EntityManager
@Transactional
@Repository
class SomeRepository {
@Autowired
EntityManager manager;
public SomeClass findById(Long id) {
return manager.find(SomeClass.class, id);
}
public void createAndUpdate(Course course) {
manager.persist(course); // entity is stored in db
course.setName("new name");
// even though I do not ask explicitly to merge
// the entity in db => entity is updated
// because the method is declared to be transactional
}
public void detachExample(Course course) {
manager.persist(course);
maanger.detach(course);
// entity is not tracked any more by manager
// => following update is not happening
course.setName("new name");
}
public void clearExample(Course course) {
manager.persist(course);
maanger.clear();
// no entity is tracked by manager
// => course is not updated
course.setName("new name");
}
public void refreshExample(Course course) {
manager.persist(course); // course has name "Bla"
course.setName("new name");
maanger.refresh(course);
// refresh loads current representation of course
// => course will have name "Bla" at this point
}
}
Hibernate annotations
@Entity
class Course {
@UpdateTimestamp
private LocalDateTime lastUpdatedDate;
@CreationTimestamp
private LocalDateTime createdDate;
}
Working with dates
java.sql.Date vs java.util.Date vs java.time.LocalDate
Named queries
@Entity
@NamedQuery(name="my_query", query="select c from course c")
class Course {
void theMethod(){
TypedQuery<Course> =
EntityManager.createNamedQuery(
"my_query",
Course.class);
}
}
@Entity
@NamedQueries(value = {
@NamedQuery(name="my_query", query="select c from course c"),
@NamedQuery(.....)
})
class Course {
}
Native queries
@Transactional
@Repository
class SomeRepository {
@Autowired
EntityManager manager;
public void theMEthod() {
manager.createNativeQuery(
"select * from person",
Person,class);
}
// native queries are useful for massive update
}
Transactional
comment | |
javax @Transactional | manage transaction over single DB |
spring @Transactional (isolation=...) | manages transactions over several DBs (if you call many DBs in one method) |
Spring Data JPA
// you can quickly expose repo as REST using spring-data-rest
@RepositoryRestResource(path="...")
interface MyRepo extend JpaRepository<Course, Long> {
// provided out of the box
//Optional<Course> course = findById(Long id);
// ...
// custom queries
List<Course> findByName(String name);
List<Course> findByNameOrderByIdDesc(String name);
int countByName(String name);
@Query("Select c From Course c where name like 'bla'")
List<Course> coursesWithBlaName();
}
public class MyUnitTest {
@Test
public void testSorting() {
Sort sort = new Sort(Sort.Direction.DESC, "name");
myRepo.findAll(sort);
}
@Test
public void testPagination() {
PageRequest pageRequest = PageRequest.of(0,3);
Page<Course> firstPage = myRepo.findAll(pageRequest);
Pageable secondPageable = firstPage.nextPageable();
Page<Course> secondPage = myRepo.findAll(secondPageable);
}
}
Project setup for Spring, Hibernate and Kotlin
Great article which describes how to setup Hibernate properties for Kotlin case
@MappedSuperclass
abstract class AbstractJpaPersistable<T : Serializable> {
companion object {
private val serialVersionUID = -5554308939380869754L
}
@Id
@GeneratedValue
private var id: T? = null
fun getId(): T? {
return id
}
@Version
var version: Int? = null
@Column(name = "created_at")
@CreationTimestamp
var createdAt: LocalDateTime? = null
@Column(name = "updated_at")
@UpdateTimestamp
var updatedAt: LocalDateTime? = null
override fun equals(other: Any?): Boolean {
other ?: return false
if (this === other) return true
if (javaClass != ProxyUtils.getUserClass(other)) return false
other as AbstractJpaPersistable<*>
return if (null == this.getId()) false else this.getId() == other.getId()
}
override fun hashCode(): Int {
return 31
}
override fun toString() = "Entity of type ${this.javaClass.name} with id: $id"
}
//build.gradle.kts
plugins {
...
kotlin("plugin.jpa") version "1.6.21"
}
dependencies {
implementation("org.hibernate:hibernate-core:5.6.12.Final")
implementation("org.jetbrains.kotlin:kotlin-noarg")
implementation("org.jetbrains.kotlin:kotlin-allopen")
}
Last updated