Actually, the way PHP handles sessions is much better than your Servlet example. Let me explain.
With PHP (by default) a session is represented by a file on the filesystem. When you call
session_start(), it checks to see if a file exists, and loads it if so. If not, it creates one and then locks it. This has two primary benefits. First, it is allows many processes on the same server to "share" the session data. Second, if someone attempts to DDOS your site, session data won't take it down (your bottleneck will be elsewhere, you don't need to worry about swapping or running out of memory space because you have a lot of sessions).
The serialization/deserialization methods in php are actually quite efficient as they are written in C and hence compiled. So that's not the bottleneck. The reason PHP's sessions are often called
evil is that they are blocking. When you open a session file, it gets an exclusive lock on the file (or blocks until it is done). It keeps that lock until the session is closed (Either by end of script, or by
session_write_close(). This is desirable since it prevents concurrency problems. But realize that if you have a long running request and try to make another one while it's executing, you'll block.
Now, the true beauty of the PHP method, is that you can replace the session handler with a userland session handler (Store session data in a database, memcached, NoSQL db, etc). Why is that good? Because then with the exact same code you can migrate from a single server to many. All you need to do is call
Now, as for your "I don't want to re-query the database on each request", I ask why not? All you're doing is a simple PK lookup. Unless you really mangle the schema, even the update/write/delete statements should be REALLY efficient. I'd suggest going with a Memory table (in MySQL) as it's faster and you don't really care about maintaining the data if the server restarts. If you're that concerned, install memcached and let it handle the storage of sessions (so you don't need SQL)...