I suspect the problem is that in what you have written, the insert into the question_choices table implicitly opens a second database handle, but because the first database handle has a lock on the row it just created, the second database handle can't verify the referential integrity constraint on question_id. Try writing the insert into survey_question_choices as a single sql statement using "insert into... select."
If that doesn't help: if you start the page running, and log in to sqlplus on the server as the dba, you can look at the dynamic performance views to see what statements are holding locks down. For example, the following will give you a list of locked objects, the usernames that have them locked, and the active sql statement (if any) for that session. It is a place to start, keeping in mind that a table name listed does not mean that the entire table is locked, only certain rows.
select
a.object_name,
s.username,
s.sid,
q.sql_text
from
all_objects a,
v$locked_object lo,
v$session s,
v$sql q
where
lo.object_id = a.object_id
and
lo.session_id = s.sid
and
s.sql_address = q.address (+)
and
s.sql_hash_value = q.hash_value (+)