java - Avoid hibernate session destruction between methods -
i'm writing spring boot application (spring boot 1.2.2, spring 4.1.5), rest api. i've setup spring security automatically load user, check authorization etc. upon every http request. users stored in database, use hibernate access data inside database.
in short, problem is: load user
object database using hibernate on every http request during prefilter. later receive object in restcontroller's params, it's no longer attached hibernate session. because of this, cannot access lazy collections inside user object without re-reading database first.
the question is: there way start hibernate session during prefilter , keep until http request complete?
long version, code: first of all, setup spring security it'll load user object part of authorization:
security configuration:
@configuration @component @enablewebmvcsecurity @enableglobalmethodsecurity(prepostenabled = true) public class securityconfig extends websecurityconfigureradapter { @autowired userdetailsservice userdetailsservice; @override protected void configure(authenticationmanagerbuilder auth) throws exception { auth.userdetailsservice(userdetailsservice).passwordencoder(new bcryptpasswordencoder()); } ... }
user details service, loads users database:
@service @transactional public class domainuserdetailsservice implements userdetailsservice { @autowired private userrepository userrepository; @override public userdetails loaduserbyusername(string username) throws usernamenotfoundexception { user user = userrepository.findbyusername(username); if (user == null) throw new usernamenotfoundexception("user '" + username + "' not found"); return user; } }
i want inject user object controller methods, this:
@preauthorize("hasauthority('view_account_info')") @transactional(readonly = true) @requestmapping(value = "/user/api-keys/list", method = requestmethod.get, produces = mediatype.application_json_value) public keysresponse getapikeys( @authenticationprincipal user user ) { return new keysresponse(user); }
this works fine. however, if try lazy load collection related user, exception:
@table(name = "users") public class user implements userdetails { ... @column @onetomany(mappedby = "user", cascade = cascadetype.all, fetch = fetchtype.lazy) private set<apikey> keys; ... } user.getkeys(); <-- exception here failed lazily initialize collection of role: com.sebbia.pushwit.core.domain.user.keys, not initialize proxy - no session
this happens because hiberante session closed after user object loaded during prefilter, , user
variable detached. in order attach again, have re-load database:
@preauthorize("hasauthority('manage_account_info')") @transactional(readonly = false) @requestmapping(value = "/user/api-keys/add", method = requestmethod.post, produces = mediatype.application_json_value) public keysresponse addapikey( @requestparam(required = true) string name, @requestparam(required = true) role role, @authenticationprincipal user user ) throws apikeyalreadyexistsexception { // have re-attach user object new session session session = (session) entitymanager.getdelegate(); user = (user) session.merge(user); // can change user or load of it's collections ... }
this works, seems error prone , unnecessary. i'm loading user
database twice. seems waste considering i've loaded in previous method, domainuserdetailsservice.loaduserbyusername
.
is there way start hibernate session during prefilter , keep until http request complete?
there's session per request pattern. have here description. if you're using spring there's filter implementation this.
be aware use contoversial: why hibernate open session in view considered bad practice?
Comments
Post a Comment