Renvoyer un ResultSet
Je suis en train de créer une méthode à partir d'où je peux interroger ma base de données et de récupérer un tableau entier.
Actuellement, il fonctionne très bien si j'utilise les données à l'intérieur de la méthode. Cependant, je veux la méthode pour retourner les résultats.
Je suis un java.sql.SQLException: Operation not allowed after ResultSet closed
sur le code actuel.
Comment puis-je y parvenir?
public ResultSet select() {
con = null;
st = null;
rs = null;
try {
con = DriverManager.getConnection(url, user, password);
st = con.createStatement();
rs = st.executeQuery("SELECT * FROM biler");
/*
if (rs.next()) {
System.out.println(rs.getString("model"));
}*/
} catch (SQLException ex) {
Logger lgr = Logger.getLogger(MySQL.class.getName());
lgr.log(Level.SEVERE, ex.getMessage(), ex);
} finally {
try {
if (rs != null) {
rs.close();
}
if (st != null) {
st.close();
}
if (con != null) {
con.close();
}
} catch (SQLException ex) {
Logger lgr = Logger.getLogger(MySQL.class.getName());
lgr.log(Level.WARNING, ex.getMessage(), ex);
}
}
return rs;
}
source d'informationauteur Patrick Reck
Vous devez vous connecter pour publier un commentaire.
Vous ne devriez jamais passer un
ResultSet
à travers les méthodes publiques. C'est sujette à des ressources fuit, car vous êtes obligé de garder la déclaration et la connexion ouverte. La fermeture serait implicitement fermez le jeu de résultats. Mais les laissant ouverts les ferait pendre autour de et la cause de la DB à court de ressources quand il y a trop de leur ouvrir.Carte à une collection de Javabeans comme et de le retourner à la place:
Ou, si vous êtes sur l'île de Java 7, il suffit de l'utilisation de try-with-resources déclaration fermeture automatique de ces ressources:
Par ailleurs, vous ne devez pas être de déclarer les
Connection
Statement
etResultSet
que les variables d'instance à tous les (grands threadsafety problème!!!!), ni avaler laSQLException
au point que, à tous (l'appelant n'ai aucune idée de qu'un problème est survenu), ni de fermer les ressources dans le mêmetry
(si par exemple d'ensemble de résultats à proximité déclenche une exception, l'état de connexion et sont encore ouvertes). Tous ces problèmes sont résolus dans le code ci-dessus des extraits.Si vous ne savez pas ce que vous voulez du jeu de résultats sur la récupération de fois que je suggère la cartographie de la chose complète dans une carte comme ceci:
Donc, fondamentalement, vous avez la même chose que le jeu de résultats (sans le ResultSetMetaData).
Bien, vous ne appel
rs.close()
dans votrefinally
-bloc.C'est fondamentalement une bonne idée, car vous devez fermer toutes vos ressources (connexions, des déclarations, des ensembles de résultats, ...).
Mais vous devez fermer les après vous les utilisez.
Il existe au moins trois solutions possibles:
ne ferment pas le jeu de résultats (et de connexion, ...) et nécessitent l'appelant pour appeler un "proche" de la méthode.
Cela signifie essentiellement que, maintenant, la appelant doit n'oubliez pas d'appeler à proximité et n'a pas vraiment rendre les choses plus faciles.
l'appelant de passer dans une classe qui est passée le jeu de résultats et d'appel que dans votre méthode
Cela fonctionne, mais il peut devenir un peu verbeux, comme vous aurez besoin d'une sous-classe d'une interface (peut-être un anonyme intérieur de la classe) pour chaque bloc de code que vous voulez exécuter sur le jeu de résultats.
L'interface ressemble à ceci:
et votre
select
méthode ressemblait à ceci:faire tout le travail à l'intérieur de la
select
méthode et revenir quelquesList
.C'est probablement le plus largement utilisé: itération sur le jeu de résultats et de les convertir en données personnalisées dans votre propre Otd et retour ceux.
Comme tout le monde avant moi a dit que ses une mauvaise idée de passer le jeu de résultats. Si vous utilisez le pool de Connexion de la bibliothèque comme c3p0 alors vous pouvez en toute sécurité de l'utilisateur CachedRowSet et sa mise en œuvre CachedRowSetImpl. En utilisant cela, vous pouvez fermer la connexion. Il va seulement utiliser la connexion si nécessaire. Ici est extrait de la java doc:
Voici l'extrait de code pour l'interrogation et la retourner jeu de résultats:
Voici l'extrait de code pour créer la source de données à l'aide de c3p0:
Vous pouvez utiliser le CachedRowSet objet qui est juste de ce que vous voulez:
Vous pouvez lire la documentation ici:
https://docs.oracle.com/javase/7/docs/api/javax/sql/rowset/CachedRowSet.html
Vous êtes à la fermeture de la
ResultSet
et, par conséquent, vous ne pouvez plus l'utiliser.Afin de retourner le contenu de la table, vous aurez à parcourir le
ResultSet
et en construire un par rangée de représentation (dans unList
peut-être?). Sans doute chaque ligne représente une entité, et je voudrais créer une entité pour chaque ligne.L'alternative est de fournir un objet de rappel, et votre
ResultSet
itération serait d'appel sur l'objet pour chaqueResultSet
ligne. De cette façon, vous n'avez pas besoin de créer un objet représentant l'ensemble de la table (qui peut être un problème si elle est importante)Je serais réticent à laisser aux clients de fermer l'ensemble de résultats/déclaration/connexion. Elles doivent être gérées avec soin pour éviter les fuites de ressource, et vous êtes beaucoup mieux de la manipulation de ce en un seul endroit (de préférence près de l'endroit où vous les ouvrir!).
Remarque: Vous pouvez utiliser Apache Commons DbUtils.closeQuietly() simplement et de manière fiable fermer la connexion/déclaration/resultset tuple (gestion des valeurs nulles et les exceptions correctement)