Being in the procedural world is not necessarily a bad thing. The request-response aspect of web programming often lends itself more naturally to procedural than OOP methodology--otherwise, PHP, Python and Perl wouldn't be so successful.
There are some practical obstacles to getting more benefits of OO (encapsulation in particular) inside domain objects. One is that Hibernate and other persistence layers force you to have setters for all properties and directly expose (untyped) collection instances. That makes enforcing any real invariants on the domain objects nearly impossible--for example a setter can't throw an exception if some business rule would be violated, because the rule depends on other properties that might not be loaded from the DB yet.
Once I attempted to solve this problem by making richer domain objects that wrapped the "dumb" persistent state beans. But this breaks down when you have transactions that span multiple objects/tables (as most do!)
There is a place for OOP in web applications but for transient domain/data objects constructed and thrown away in the scope of each request, the costs to get the benefits of OOP may outweigh the benefits.