Candidate with 15y experience in
#Java
and
#Spring
in 2024 does the following in an coding task. My biggest red flags:
- 🤯
- findAll() conversion
-
@Repository
use
I know Lombok's
@Data
is debatable so just a yellow flag.
Hire or no?
#Java
Tip: to make big, complex Comparator chains more readable i like to assign the Comparators to variables which names start with "by". This way the call of sorted() get smaller and reads nicely almost like natural language. Additionally you can use static imports.
#Java
@springframework
Tip: You can autowire multiple beans implementing a specific interface into a List holding all the implementations. Define the List with the generic type you want to be used. You can use constructor injection like shown below or field injection.
#Java
#JPA
@Hibernate
Tip: By default Hibernate updates all fields of an Entity when doing an update. You can use the
@DynamicUpdate
annotation on an
@Entity
and Hibernate will only update the columns that have changed.
#Java
@springframework
Tip: you can inject (autowire) beans which might be absent, wrapped in an java.util.Optional. This way you express that this bean is optional, you avoid an exception if it does not exist and can handle it's absence nicely through the Optional API.
#Java
#Bean
#Validation
Tip: The easiest way to do multi field validation without additional classes and annotations is to use
@AssertTrue
. You put it over a method returning a boolean. The method name must start with "is".
#Java
#SpringBoot
Tip: You can run a method in a Spring
@Service
just after the application has started by annotating it with
@EventListener
(ApplicationReadyEvent.class). The method can't have parameters. I sometimes misuse it to quickly test a certain method of a Spring Service
#Java
@springframework
Tip: you can convert String RequestParams directly to LocalDate at the request level using the
@DateTimeFormat
annotation. You need to specify the pattern. It can be your own or ISO patterns. No need for converting it 'manually'.
#Java
#SpringFramework
Tip: If your method is
@Transactional
and you fetch and modify an entity within this method you don't need to call the save() method of the
@SpringData
repository. The changes will be persisted to the DB when the transaction ends sucessfully - commits.
#Java
#Spring
@SpringSecurity
Tip: If you want to access the current authenticated user anywhere in the code you can use the SecurityContextHolder class. This way you don't need to pass down the Authentication object from your RestController down through multiple Services.
#Java
#JPA
@Hibernate
Tip: show-sql is the easiest (not the best!) way to see the SQL generated by Hibernate. You can config to improve it a bit by enabling formatting, showing the JPQL Query that generated the query and enable highlighting that adds some color to the output.
#Java
@SpringFramework
@SpringData
Tip: To do things in a database transaction you can use Spring's TransactionTemplate instead of the
@Transactional
annotation. It might save you from problems like self-invocation and other pit-falls with this annotation.
#Java
Tip: to get all days of a month you can start with w YearMonth object, get it's first day and then use the datesUntil() function which returns a Stream of all days until the specified date.
#Java
@SpringData
Tip: If you use hibernate.use_sql_comments to show which JPQL Query caused which SQL Query you can optionally use Spring Data JPAs (@)Meta annotation to set a custom comment for your JPQL Query.
#Java
@SpringFramework
Tip: when creating standard HttpHeaders for Spring MVC Responses instead of providing them as Strings some have dedicated Builders which allow you to create the headers in a more type-safe way. See HttpHeaders set() methods which you can configure that way.
#Java
@springframework
Tip: the easiest way to create dynamic
#SQL
Queries in
#JPA
is Query By Example. You create a sample object which you wrap into an Example and then pass is to your
@SpringData
repository. JPA will create a WHERE clause only with the fields you have set.
#Java
@springboot
Tip: if you want to know when a
#JPA
Transaction start and ends, how queries resuse existing transaction in a
@Transactional
method or TransactionTemplate enable DEBUG logging for `org.springframework.orm.jpa`.
#Java
#JPA
@SpringData
Tip: Usually when sorting in Spring Data we provide the property on which we want to sort as a String. There is however a TypedSort class which gives us the possibility to pass a Function as the parameter to sort. This increases the type-safety of our code.
#Java
#JPA
@Hibernate
Tip: Hibernate 6 changed the way it reads the underlying JDBC ResultSet from read-by-name to read-by-position. Thanks to this change after the upgrade you get cleaner SQL queries with no column aliases 👍
A pitfall when using
#java
@springframework
@Transactional
annotation is self-invocation. In the code below you'd expect in that the first save() will be rolled back. But it won't. To work properly the
@Transactional
method needs to be called from another service.
#Java
@SpringData
Tip: when using interface based Projections you can reach into nested objects by adding the `path` to the getter method. Take a look how getDepartmentDeptName gets the deptName from the Department entity.
#Java
#JDBC
#Database
Tip: Add to your JDBC URL the ApplicationName (depends on DB, not every DB has it!) property. This way in the session list you'll see the set name instead of the JDBC driver name. This helps you troubleshooting when multiple apps connect to the same DB.
#Java
Tip: If you want to get the message of the root cause you can get it safely and easily using Apache Commons ExceptionUtils. The getRootCauseMessage(Exception ex) methods gives you the message in the form {ClassNameWithoutPackage}: {ThrowableMessage}
The Range class from
#Apache
Commons let's you work nicely with ranges of numbers or dates. It has functions to check wheter values are in, before or after a range. The same goes for ranges. Nice, since the built in
#Java
Date API does not have a class for a period of time.
Another creative
#Lombok
usage:
"We forbid using
@Autowired
and field injection because we read on the internet that it's bad. But you know if we have lot's of dependencies the constructors look big and ugly. So we use Lomboks
@RequiredArgsConstructor
. 🤪
I hate calling
#Java
#Spring
classes ***Impl. Say BillingService -> BillingServiceImpl. Beacuse when a second implementation arrives how would you name it - BillingServiceImpl2? I'd prefer much more DefaultBillingService or sth like that.
#Java
Tip: You're in a method doing some complex stuff and want to return more then one 'thing'? You can quickly inline a Java Record and use it inside your class to return those two 'things'. It doesn't need to be in a separate file and imported.
Most
#Java
#JPA
projects i've seen have some kind of BaseEntity class which has the id field. But did you know that
@SpringData
offers such a class? It's called AbstractPersistable. Maybe it suits your needs and you don't need your own BaseEntity.
#Java
#JPA
@Hibernate
5.4.5+ Tip: If you set the property .log.LOG_QUERIES_SLOWER_THAN_MS to a value you want Hibernate will log all queries which took longer. This way you can faster identify queries which you might need to optimize.
Cool
#Java
@springframework
feature:
If you want to know when a given cron expression will match you can use Spring's CronExpression class.
It takes a cron expr and using the next() method you can determine the next match after the provided point in time.
I hate it when in
#Java
#JPA
project people reject the usage of native SQL queries because it not portable and some day this century we might change the DB.
#Java
#JPA
@Hibernate
Tip: If by accident you already use the Metamodel Generator in your project you can use the generated model classes in the mappedBy attribute of your relationships to get a bit more type-safety.
In a
#Java
constructor Optional is used to set fields.
In the first approach i need to read to the end to see which field is being set. I find that harder to read.
The latter approach tells me what is being set, then how and what the default value will be.
What do you think?
#Java
#JPA
Tip: Setting a
@Column
to updateable=false has the effect that the JPA implementation will omit this column when doing an update statement. It won't throw an exception. It has no no effect on the database. You can still update the column outside of Hibernate.
#Java
#programming
Tip: if you don't like that the standard Java substring method throws an Exception if the String is shorter then expected you can use Apache Commons StringUtils which dont throw an Exception in that case and happily return what they can.
#Java
#JPA
@hibernate
Tip: If you are using Strings to configure Hibernate you can do a bit better. The interface AvailableSettings has constants for this strings. Benefit of using this is a bit more type safety and JavaDoc for this constants 👉
#Java
Tip: if you need to work with API that requires a List<String> but you want to work with Java 14 Text Blocks you can easily convert it to List. With Java 17 you can first call lines() on the String which returns a Stream and then directly toList() which gives the List.
#Java
@springframework
Tip:
#SpringFramework
has a class called DataSize which can help you with the conversion between byte size units from bytes up to terabytes. The amount needs to be of type long. Fractions are not supported.
#Java
Tip: When you have to use some class, and you have to override it's behavior a bit to suit your needs it's always worth checking the docs if there is already a class down the hierarchy which already does what you want or allows minimize the code you have to write.
In
#Java
@springframework
you can autowire a List of beans implementing a certain interface like this. No need to manuall specifying fields and adding them into the List in
@PostConstruct
method.
#Java
#Lombok
Tip: Take care when using Lombok's
@AllArgsConstructor
. To generate the constructor it uses the order of the Fields in the class. If Fields have the same type and you rearrange them you start writing into different fields and the compiler can't help.
As much as i like
@Hibernate
Statistics to troubleshoot performance problems as much i don't like it gives the times in nanoseconds. So hard to convert it in my head into miliseconds.
From all the technologies i worked with
@Hibernate
has by far the best docs. Very well structured and with some funny parts like when they are begging not to use and marking legacy parts with a 💀: 😉,
#Java
@Hibernate
6
@springboot
Tip: To implement Row-level (Shared schema) multitenancy you need just two classes. A BaseEntity with the
@TenantId
annotation to save the tenant for each row and a resolver to determine the current Tenant. Entities needs to extend this BaseEntity.
#Java
#JPA
@Hibernate
Tip: Until Hibernate 6 a proper configuration required the correct dialect to be set for the used DB. From v6 onwards this is not needed anymore. Hibernate 6 determines now the correct Dialect based on the JDBC URL and JDBC Metadata.
I find the JavaDoc
@author
tag useless. I mean code changes and after some time the original author might have nothing to do with the code. I remove this where i can.
#Java
Tip: Use Apache Commons Lang3 EnumUtils to gracefully handle Enums. The standard java Enum class throws Exceptions when you pass an incorrect value. But EnumUtils returns safely plain null. There is even a ignoreCase method to get an enum value.
#Java
Tip: how to get the first and last day of the current month. Without and with time part (LocalDate/LocalDateTime). How could we life prior to Java 8? 😉
I rarely download projects from . But when i do i drives me nuts that the default is now gradle and i have to download it twice - second time with maven.
#Java
thought: every time i work with Optional.ofNullable() i wish the
@java
creators would make .of(val) accept a nullable value and for the not-null case provide .ofNotNull(val). Nullable values are the default use case of Optional and should use the shorter method name.
@niebezpiecznik
Dali by jakiś generyczny tekst typu: `Aplikacja zaktualizowana pomyślnie`, 'mojePGNiG - wkrótce nowe funkcjonalności', .... nikt by się nie przyczepił.
#Java
#JPA
@SpringData
Tip: The easiest way to map a SQL Native Query to an Object is an interface projection. You define an interface and get() methods with names matching the returned columns. Nice way to map SQL Views. IMO a leaner approach then immutable Entities.
As pointed out in the comments: While this technically works it isn't a good idea because it only works in JPA. It won't work in other Spring Data modules. This way also Spring Data doesn't emit Domain Events.
Sorry, for the not so great Tip.
#Java
#SpringFramework
Tip: If your method is
@Transactional
and you fetch and modify an entity within this method you don't need to call the save() method of the
@SpringData
repository. The changes will be persisted to the DB when the transaction ends sucessfully - commits.
@InfZakladowy
Mam 10 lat doświadczenia. Nie ćwiczę. Uda to się uda, nie to nie. Pracy jest pełno. Nie ma sensu się stresować przed. Albo ogarnę doświadczeniem rozmowę, albo nie.
#Java
#JPA
@Hibernate
Tip: a way to learn more about
#Hibernate
is to enable SQL logging. Then execute the function you want and look at the generated SQL Queries. If they dont match what you'd expect to be generated find out what caused the queries and find the solutions.
@springframework
Tip: if you are not on
#Java
21 and want nicely get the first or last element of a List or Set you can use firstElement() and lastElement() from
#SpringFramework
CollectionUtils. It handles if the passed List or Set is null or empty and throws no Exception.
Using
@springframework
is like using a Ferrari. It has so much power, so many possibilities. You don't have to use it every day, but it's good to know that if a need arises, you have the power, the capabilities.
I don't write much technical documentation but when i do i try it to do as close as possible to the code. The next developer will rather look in the code then in confluence.
@maciejwalkowiak
I'm there for over 2 years now and I'm going back to java next month. I don't really see any aspect node does better then a modern Java Backend.
#Java
#JPA
Tip: When mapping enums by default the the ordinal number is stored in the DB. This is error prone and not readable. It's better to save the enums as Strings. You can use the
@Enumerated
(EnumType.STRING) annotation to do this.
2020: Make this functionality and make it generic beacuse we might/will have cases like this.
3yrs later: Second use case arrives totally different then first one.
I hate doing things generic because something might/will happen. I'd rather refactor when i see the second use case