One other valid alternative (which I used several times) is saving the data in temporary records in your database entities. Any "Next" or "Previous" operations in the wizard should save the object in the database (so that the data input by the user is saved between the several screens). The database record is created in the first step of the screen and its identifier is passed between the several wizard screens.
In case your application only accepts records which creation was done executing all the steps in the wizard (i.e. the user did not leave in the middle), you would have to have a field "WizardNotFInished" on your entities that would make it possible to "exclude" the unfinished records from the application logic. Of course, this field is true when the record is created in the first step of the wizard and set to false in the last step.
Comparing this solution with the usage of session variables, I would say that with this one you have three advantages:
- You can easily reuse the wizard screens as edit screens (they receive an ID and edit a database record)
- It is easier to develop and maintain (you can use the Entities and Fields directly in your screens without the need for intermediate structures)
- It is more performant (no need for session variables)
The disadvantage would be the fact that you must deal with incomplete database records in all the business logic of the application (maybe even create a timer that deletes records created in wizards that were never finished).