Tales from the jar side: Calling stored procedures using Spring Data, Hyperbullet chess by a candidate, and the Supreme Court voted 6 - 3 that you must subscribe to this newsletter
Dad joke: This morning I saw a guy dragging a clam on a leash. It must be hard to walk with a pulled mussel (rimshot)
(NOTE: Substack now supports adding an audio voice over to the newsletter, so if you’d rather hear me read it to you, use the embedded player. Let me know if you want me to continue that in the future.)
Welcome, fellow jarheads, to Tales from the jar side, the Kousen IT newsletter, for the week of June 19 - July 3, 2022. This week I taught both an O’Reilly Media online course and an NFJS Virtual Workshop on Spring Data JPA.
Regular readers of this newsletter are affectionately known as jarheads, and are far more intelligent, sophisticated, and attractive than the average newsletter reader. If you wish to become a jarhead, please subscribe using this button:
As a reminder, when this message is truncated in email, click on the title at the top to open it in a browser tab formatted properly for both the web and mobile. This issue is a long one, so go for it. :)
The Right Tool For The Job
I taught a Spring Data course this week (actually, two of them, which were different but pretty similar). That’s a tough course to teach, because Spring Data JPA is an abstraction layer on top of the Java Persistence API (JPA) — which is changing to the Jakarta Persistence API, but let’s not deal with that now — which itself is an Object-Relational Mapping (ORM) abstraction layer on top of SQL.
In other words, in that course, I needed to cover:
The basics of Spring
The basics of JPA and ORM tools in general
The basics of Hibernate, which is the JPA persistence provider used by Spring
all in 4 hours. You could argue that the students ought to have basic Spring experience as a prerequisite, and we do, but that is largely ignored. You could also argue that we should have a separate class on just Hibernate/JPA, and I think that would be a good idea, but neither O’Reilly nor NFJS want to hold that class, and doing Hibernate without Spring is no fun anyway.
I do what I can. Near the very end, however, I get into a more philosophical question. If you check the documentation on Spring Data JPA, it includes a section on how to call stored procedures using the Spring Data library. For a demo, I like to use the Sakila sample database from MySQL, which has a few stored procedures in it.
(For those who like random trivia, the word “Sakila” is basically the letters SQL with some vowels thrown in to make it pronounceable, more or less. It’s also the name of their dolphin mascot:
The database has a stored procedure called film_in_stock, which takes three arguments:
An input integer representing the store ID
An input integer representing the film ID
An output integer that returns how many copies of that film are available at that store
The sample on the web site looks like:
mysql> CALL film_in_stock(1,1,@count);
+--------------+
| inventory_id |
+--------------+
| 1 |
| 2 |
| 3 |
| 4 |
+--------------+
4 rows in set (0.01 sec)
Query OK, 1 row affected (0.01 sec)
mysql> SELECT @count;
+--------+
| @count |
+--------+
| 4 |
+--------+
1 row in set (0.00 sec)
The result is that there are four copies of film 1 at store 1.
I have a GitHub repository that works with that sample database. In it, I try to follow the Spring Data JPA documentation on calling stored procedures by adding a @NamedStoredProcedureQuery
annotation to the Film
entity, which looks like:
@NamedStoredProcedureQuery(name = "Film.inStock",
procedureName = "film_in_stock", parameters = {
@StoredProcedureParameter(mode = ParameterMode.IN,
name = "p_film_id", type = Integer.class),
@StoredProcedureParameter(mode = ParameterMode.IN,
name = "p_store_id", type = Integer.class),
@StoredProcedureParameter(mode = ParameterMode.OUT,
name = "p_film_count", type = Integer.class)
})
Then I add a couple of abstract methods to the FilmRepository
interface:
@Procedure(procedureName = "film_in_stock")
Integer numberOfFilmsInStock(Integer p_film_id,
Integer p_store_id);
@Procedure(name = "Film.inStock")
Integer filmsInStockAtStore(Integer p_film_id,
Integer p_store_id);
I provided a couple of tests for this in FilmRepositoryTests
, but here’s the thing: In Spring Boot 2.6.3, both tests pass. In Spring Boot 2.7.0 and above, both fail. For some reason, starting in 2.7, calling the stored procedure this way returns an integer collection made up of those inventory_id
values shown above, but doesn’t count them. I have no idea why, or what changed between 2.6.3 and 2.7 that might cause this.
I’ve spent a lot of hours trying to track this down, but in my opinion there’s a philosophical issue involved:
Why am I using Hibernate/JPA to called a stored procedure anyway?
As the saying goes, if all you have is a hammer, everything looks like a nail:
Spring already has a class for calling stored procedures, called SimpleJdbcCall
. If you look at my class called FilmDao
in the same repository, you’ll see that I instantiate that class for the proper stored procedure, call it using the input parameters, and it works like a charm. See the class FilmDaoTest
in the repository for the details.
Hibernate and JPA are all about object-relational mappings. If all I want to do is call a stored procedure, there aren’t any objects involved, so why go through a whole layer dedicated to that? Or, in the immortal words of Ian Malcolm in the first (and only good) Jurassic Park movie:
There’s already a direct way to call a stored procedure. No need to overcomplicate things. Though arguably I ought to take the time to report what I’m pretty sure is a bug in Spring Data.
Firouzja Under Fire
I mentioned in the last couple of newsletters that the Candidates Tournament is going on to determine the challenger to (chess) World Champion Magnus Carlsen. One of the competitors, and by far the youngest at only 19 years old, is Alireza Firouzja, formerly of Iran and now playing for France.
Firouzja is a tactical wizard and extremely fast, making him quite popular, especially online. He’s great fun to watch, creating combinations seemingly out of nowhere. Great attacking players are always fun, and this kid has a real gift. Everyone acknowledges his extraordinary talent. Most observers believe he will be a threat to the World Championship for years to come.
That someday, however, isn’t going to be this cycle. After qualifying for this year’s Candidates Tournament, Firouzja took about six months off from playing major tournaments, presumably to prepare.
Firouzja doesn’t play for draws. His style is very ambitious, which can be deadly against lower rated players. This tournament, however, has many of the best players in the world, and against players that advanced, that sort of style is risky. He drew his first three games, and was worse in each of them. Then he lost to the eventual winner, Ian Nepomniachtchi, then drew, and then lost again. He only won one game in the double round-robin tournament, and was sitting at the bottom of the table, when he was scheduled to face the leader again and decided to blow off some steam the night before that game:
My first clue that anything was up was this tweet by Magnus:
It turned out that Firouzja logged into the free chess server lichess and played a series of hyperbullet games. What’s hyperbullet? You’ve probably heard of blitz chess, where each side gets five minutes or less for the game. Bullet chess is defined as only one minute (!) for the entire game, which is very fast but fun as a spectator sport. Hyperbullet is a blindingly fast 30 seconds (!!) for each side for the entire game.
There was a bit of an outcry.
As this article describes:
After losing to Hikaru Nakamura on Wednesday, Firouzja logged onto lichess.com around 11:00 p.m. Madrid time and started playing hyper-bullet chess. Playing exclusively 30-second games in the middle of a classical chess tournament with hours on the clocks seems like a pretty straightforwardly bad idea; doing so at the expense of sleep, 10 rounds deep into a 14-round tournament, is even worse. Firouzja played a few games, logged off until 1:00 a.m. Thursday morning, then began the true marathon element of the binge. Firouzja took on fellow grandmaster Daniel Naroditsky in a best-of-250 hyper-bullet showdown. He stopped playing at 5:43 a.m., after 337 games.
Um, that’s a lot, and didn’t go over well with the chess community. In his next game, he played overly aggressively again and lost for the fourth time, finishing at the bottom of the tournament.
Old fogeys didn’t like it.
My attitude is, the kid was very disappointed and decided to vent the way he always does. He made a questionable decision, but he wasn’t in contention any more and I can imagine he was unhappy about it.
Most of all, he’s still a kid. This was a tough tournament for him, but he’ll bounce back. I’m just glad I don’t have to defend the decisions I made as a 19-year-old in such a public forum.
Yesterday (Saturday) was an off-day during the tournament. Chess24 decided to sponsor a blitz tournament in a park in Madrid that day, and Magnus asked Hikaru Nakamura (one of the candidates still in contention) to play:
Hikaru couldn’t help poking fun:
Firouzja apparently (and wisely) decided against it. :)
Tweets and More
Existential Question
Oh wow, a Ship of Theseus joke. In case you don’t know (or don’t remember), the idea behind the Ship of Theseus is that if every part of Theseus’s ship is replaced over time, is it still the same ship? If not, at what point does it become a new ship? If it’s the same ship, what if you disassembled every part and rebuilt a new ship with those parts, would it still be the ship of Theseus?
(Related: when Scotty beams you up, are you the same person or a new one? See the blog post / video Is Star Trek’s Famous Transporter Really A Death Machine?)
I’m a developer, so the answer depends on how the person who wrote the Ship
class overrode the equals
method, which actually defines equivalence, rather than equality. They say life would be a lot easier if we could just get a look at the source code, but I’m not so sure.
The Peasants Are Revolting, Literally
For the record, if a quantity takes integer values, use “fewer,” otherwise it’s “less.” That rule (and its many exceptions) is discussed in this page by Merriam-Webster.
Supreme Court Jokes
It’s probably not a good sign if your decisions immediately become a meme.
Sigh. Or this one:
Presumably they would also vote 6 - 3 that we must kneel before Zod.
Galactus is a Destroyer of Worlds, whose coming is announced by the Silver Surfer, the Herald of Galactus. Thus this reply:
Here is the Silver Surfer:
Yup, that’s a faster-than-light traveling surfboard, yet even more evidence that the early Marvel comics writers were on serious drugs. Galactus and the Silver Surfer were common in the Fantastic Four series, so now that they’re presumably back in the Marvel fold (under the all-encompassing Disney empire), I imagine both will show up in future Marvel movies.
A couple of developer-focused variations of the same meme:
On a Friday, before a holiday weekend, without tests. In a concurring opinion, Justice Thomas said, “YOLO.”
(For those not in the know, merging the “development” branch into “production” is virtually a guarantee of problems.)
Hey, what could go wrong?
(Well, everything, but that’s why we watch.)
Have a good week everybody.
As a reminder, you can see all my upcoming training courses on the O’Reilly Learning Platform here and all the upcoming NFJS Virtual Workshops here.
Last week:
Spring Data Fundamentals, on the O’Reilly Learning Platform
Spring Data and the Java Persistence API, an NFJS Virtual Workshop
This week:
Introduction to the Gradle Build Tool, Gradle, Inc.
Cool! Listening to you read the Jar letter is like listening to a audible book, not something I would want to do for hours, but 15 minutes was enjoyable. YOLO!