Vytvoření sloupce typu text ve Spring Data a PostgreSQL

Pokud necháváte databázové tabulky vytvářet Springem, následující entita

@Entity
@Table(name = "t_my_entity")
class MyEntity (
    @Id
    var id: Long,
    var name: String
)

se vytvoří jako tabulka t_my_entity se sloupcem name typu varchar o maximální velikosti 256 znaků. Pokud potřebujete typ text (retězec o neomezené velikosti) je třeba přidat annotaci.

@Column(columnDefinition = "TEXT")
var input: String

Zajímavá nastavení lockback

Základní konfigurační soubor lockback.xml

<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <root level="info">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>

Zapnutí debug režimu pro lockback

Číst dálZajímavá nastavení lockback

Jak vytvořit like dotazy ve Spring Data

V tomto příspěvku ukáži, jak lze vytvořit sql dotazy s LIKE ve Spring Data bez pomoci @Query anotace. Budeme mít entitu kniha

@Entity
@Table(name = "t_book")
@SequenceGenerator(initialValue = 100, name = "t_book_seq_gen", sequenceName = "t_book_seq")
class BookEntity (
        @Id
        @GeneratedValue(generator = "t_book_seq_gen", strategy = GenerationType.SEQUENCE)
        var id: Long = 0L,

        var author: String = "",

        var publisher: String = "",

        var title: String = "",

        ...
)

a vytvoříme si jpa repository

Číst dálJak vytvořit like dotazy ve Spring Data

Spring CommandLineRunner

CommandLineRunner je funkční rozhraní s metodou void run(String... args) throws Exception. V této metodě můžeme uvést vše, co chceme aby se stalo a startu aplikace. Jednou z možností jak vytvořit CommandLineRunner je vlastní třída s anotací @Configuration a následně metoda s anotací @Bean vracející CommandLineRunner

@Configuration
class AppConfig {

    @Bean
    fun init(bookRepository: BookRepository): CommandLineRunner {
        return CommandLineRunner {
            bookRepository.save(BookEntity(title = "Cyber Leviathan"))
            bookRepository.save(BookEntity(title = "Last Hunt"))
        }
    }
}

Jiný způsob je extendovat CommandLineRunner a implementovat metodu run()

@SpringBootApplication
class SpringData2Application : CommandLineRunner {
	override fun run(vararg args: String?) {
		println("Running ...")
	}
}

fun main(args: Array<String>) {
	runApplication<SpringData2Application>(*args)
}

 

Vytvoření tabulek pro spring batch

Spring Batch obsahuje inicializační SQL skripty pro většinu populárních databází (více v tomto příspěvku). Spring Boot dokáže detekovat databázi a spustit správný skript při startu aplikace. Pokud chcete, aby Spring Batch vytvořil potřebné tabulky, přidejte do konfiguračního souboru

spring.batch.initialize-schema=always

Vypnutí této funkcionality

spring.batch.initialize-schema=never

Zdroj: https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-initialize-a-spring-batch-database

Micrometer a DistributionSummary

Pokud použijeme micrometer a objekt DistributionSummary, zde jsou ukázky výstupu na actuatoru:

Pokud máme hodnoty

500, 1500, 2500, ..., 9500

a

val summary = DistributionSummary.builder("my.summary").baseUnit("miliseconds").register(meterRegistry)

a hodnoty uložíme/nahrajeme

summary.record(hodnota)

výsledek (na endpointu /actuator/prometheus)

# HELP my_summary_miliseconds
# TYPE my_summary_miliseconds summary
my_summary_miliseconds_count 10.0
my_summary_miliseconds_sum 50000.0
# HELP my_summary_miliseconds_max
# TYPE my_summary_miliseconds_max gauge
my_summary_miliseconds_max 9500.0

Další možnosti:

Číst dálMicrometer a DistributionSummary

Projekce a Query

V předchozím příspěvku jsem ukázal základní možnost projekce ve Spring Data. Na pár věcí je ale třeba si dávat pozor. Je možné používat @Query a také nativní @Query(nativeQuery = true), ale je třeba specifikovat název výsledného sloupce pomocí klíčového slova AS.

@Query("SELECT b.title AS title, b.numberOfPages AS numberOfPages FROM BookEntity b")
fun findAllInfo(): List<BaseBookInfo>

@Query("SELECT b.title AS title, b.numberOfPages AS numberOfPages FROM t_book b", nativeQuery = true)
fun findAllInfoNative(): List<BaseBookInfo>

Pokud byste to neudělali, našel by se sice správný počet záznamů, ale všechny záznamy by měly všechny hodnoty null (nebo by došlo k vyhození výjimky v případě přístupu k primitivním datovým typům).

Spring Data a projekce

Pokud pro dotazování používáte Spring Data, v rámci výsledku dostanete root entitu (všechny její hodnoty). Pokud tedy budete mít následující entitu:

@Entity
@Table(name = "t_book")
@SequenceGenerator(initialValue = 100, name = "t_book_seq_gen", sequenceName = "t_book_seq")
class BookEntity (
        @Id
        @GeneratedValue(generator = "t_book_seq_gen", strategy = GenerationType.SEQUENCE)
        var id: Long = 0L,

        var author: String = "",

        var publisher: String = "",

        var title: String = "",

        var foreword: String = "",

        var numberOfPages: Int = 0,

        var publishingYear: Int = 0
)

vždy získáte všechny hodnoty (id, author, publisher, title, foreword, numberOfPages, …), i když je nebudete vždy potřebovat. Pokud chcete použe některé hodnoty, je zde možnost tzv. projekce. Vytvoříte si rozhraní, které bude obsahovat jen to, co potřebujete. Např. budete chtít pouze titul knihy a počet stran.

Číst dálSpring Data a projekce

Plánování pomocí kronu

Pokaždé, když bude 9 vteřina
9 * * * * ?
2020-07-04 13:16:09.057000
2020-07-04 13:14:09.011000
2020-07-04 13:13:09.004000

Pokaždé, když bude 20 mituta a 5 vteřina
5 20 * * * ?
2020-07-04 13:20:05.109000

Pokaždé, když bude 18 vteřina, 34 minuta a 13 hodina
18 34 13 * * ?

Pokaždé, když bude 0 vteřina, 50 minuta, 13 hodina a 24 den v měsíci
0 50 13 24 * ?

 

Takový to kron string se dá použít například při plánování jobů ve spring batch:

application.properties -> app.jobs.cron: 0 35 13 24 *
konfigurace jobu -> @Scheduled(cron = "\${app.jobs.cron}")