2014-06-17 95 views
0

我得到这个异常:的ClassNotFoundException为P6SPY试图登录SQL时请求

java.lang.ClassNotFoundException: com.p6spy.engine.spy.P6SpyDriver 

尝试连接到通过P6SPY代理驱动我的数据库。此异常指着这行代码:

Class.forName("com.p6spy.engine.spy.P6SpyDriver"); 

我加入了P6Spy.jar和spy.properties的构建路径,这里是spy.properties配置文件:

################################################################# 
# P6Spy Options File           # 
# See documentation for detailed instructions     # 
################################################################# 

################################################################# 
# MODULES              # 
#                # 
# Modules provide the P6Spy functionality. If a module, such # 
# as module_log is commented out, that functionality will not # 
# be available. If it is not commented out (if it is active), # 
# the functionality will be active.        # 
#                # 
# Values set in Modules cannot be reloaded using the   # 
# reloadproperties variable. Once they are loaded, they remain # 
# in memory until the application is restarted.     # 
#                # 
################################################################# 

#module.log=com.p6spy.engine.logging.P6LogFactory 
#module.outage=com.p6spy.engine.outage.P6OutageFactory 

################################################################# 
# REALDRIVER(s)             # 
#                # 
# In your application server configuration file you replace the # 
# "real driver" name with com.p6spy.engine.P6SpyDriver. This is # 
# where you put the name of your real driver P6Spy can find and # 
# register your real driver to do the database work.   # 
#                # 
# If your application uses several drivers specify them in  # 
# realdriver2, realdriver3. See the documentation for more  # 
# details.              # 
#                # 
# Values set in REALDRIVER(s) cannot be reloaded using the  # 
# reloadproperties variable. Once they are loaded, they remain # 
# in memory until the application is restarted.     # 
#                # 
################################################################# 

# oracle driver 
realdriver=oracle.jdbc.driver.OracleDriver 

# mysql Connector/J driver 
# realdriver=com.mysql.jdbc.Driver 

# informix driver 
# realdriver=com.informix.jdbc.IfxDriver 

# ibm db2 driver 
# realdriver=COM.ibm.db2.jdbc.net.DB2Driver 

# the mysql open source driver 
#realdriver=org.gjt.mm.mysql.Driver 

#specifies another driver to use 
#realdriver2= 
#specifies a third driver to use 
#realdriver3= 


#the DriverManager class sequentially tries every driver that is 
#registered to find the right driver. In some instances, it's possible to 
#load up the realdriver before the p6spy driver, in which case your connections 
#will not get wrapped as the realdriver will "steal" the connection before 
#p6spy sees it. Set the following property to "true" to cause p6spy to 
#explicitily deregister the realdrivers 
deregisterdrivers=false 

################################################################ 
# P6LOG SPECIFIC PROPERTIES         # 
################################################################ 
# no properties currently available 

################################################################ 
# EXECUTION THRESHOLD PROPERTIES        # 
################################################################ 
# This feature applies to the standard logging of P6Spy.  # 
# While the standard logging logs out every statement   # 
# regardless of its execution time, this feature puts a time # 
# condition on that logging. Only statements that have taken # 
# longer than the time specified (in milliseconds) will be  # 
# logged. This way it is possible to see only statements that # 
# have exceeded some high water mark.       # 
# This time is reloadable.          # 
# 
# executionthreshold=integer time (milliseconds) 
# 
#executionthreshold= 

################################################################ 
# P6OUTAGE SPECIFIC PROPERTIES         # 
################################################################ 
# Outage Detection 
# 
# This feature detects long-running statements that may be indicative of 
# a database outage problem. If this feature is turned on, it will log any 
# statement that surpasses the configurable time boundary during its execution. 
# When this feature is enabled, no other statements are logged except the long 
# running statements. The interval property is the boundary time set in seconds. 
# For example, if this is set to 2, then any statement requiring at least 2 
# seconds will be logged. Note that the same statement will continue to be logged 
# for as long as it executes. So if the interval is set to 2, and the query takes 
# 11 seconds, it will be logged 5 times (at the 2, 4, 6, 8, 10 second intervals). 
# 
# outagedetection=true|false 
# outagedetectioninterval=integer time (seconds) 
# 
outagedetection=false 
#outagedetectioninterval= 

################################################################ 
# COMMON PROPERTIES           # 
################################################################ 

# filter what is logged 
filter=false 

# comma separated list of tables to include when filtering 
include  = 
# comma separated list of tables to exclude when filtering 
exclude  = 

# sql expression to evaluate if using regex filtering 
#sqlexpression = 


# turn on tracing 
#autoflush = true 

# sets the date format using Java's SimpleDateFormat routine 
dateformat=yyyy-MM-dd 

#list of categories to explicitly include 
#includecategories= 

#list of categories to exclude: error, info, batch, debug, statement, 
#commit, rollback and result are valid values 
excludecategories= 


#allows you to use a regex engine or your own matching engine to determine 
#which statements to log 
# 
#stringmatcher=com.p6spy.engine.common.GnuRegexMatcher 
#stringmatcher=com.p6spy.engine.common.JakartaRegexMatcher 
#stringmatcher= 

# prints a stack trace for every statement logged 
stacktrace=false 
# if stacktrace=true, specifies the stack trace to print 
#stacktraceclass= 

# determines if property file should be reloaded 
#reloadproperties=false 
# determines how often should be reloaded in seconds 
#reloadpropertiesinterval=60 

#if=true then url must be prefixed with p6spy: 
useprefix=true 

#specifies the appender to use for logging 
#appender=com.p6spy.engine.logging.appender.Log4jLogger 
#appender=com.p6spy.engine.logging.appender.StdoutLogger 
appender=com.p6spy.engine.logging.appender.FileLogger 

# name of logfile to use, note Windows users should make sure to use forward slashes in their pathname (e:/test/spy.log) (used for file logger only) 
logfile  = D:/spy.log 

# append to the p6spy log file. if this is set to false the 
# log file is truncated every time. (file logger only) 
append=true 

#The following are for log4j logging only 
#log4j.appender.STDOUT=org.apache.log4j.ConsoleAppender 
#log4j.appender.STDOUT.layout=org.apache.log4j.PatternLayout 
#log4j.appender.STDOUT.layout.ConversionPattern=p6spy - %m%n 

#log4j.appender.CHAINSAW_CLIENT=org.apache.log4j.net.SocketAppender 
#log4j.appender.CHAINSAW_CLIENT.RemoteHost=localhost 
#log4j.appender.CHAINSAW_CLIENT.Port=4445 
#log4j.appender.CHAINSAW_CLIENT.LocationInfo=true 

#log4j.logger.p6spy=INFO,STDOUT 


################################################################# 
# DataSource replacement          # 
#                # 
# Replace the real DataSource class in your application server # 
# configuration with the name com.p6spy.engine.spy.P6DataSource,# 
# then add the JNDI name and class name of the real   # 
# DataSource here        # 
#                # 
# Values set in this item cannot be reloaded using the   # 
# reloadproperties variable. Once it is loaded, it remains  # 
# in memory until the application is restarted.     # 
#                # 
################################################################# 
#realdatasource=/RealMySqlDS 
#realdatasourceclass=com.mysql.jdbc.jdbc2.optional.MysqlDataSource 

################################################################# 
# DataSource properties           # 
#                # 
# If you are using the DataSource support to intercept calls # 
# to a DataSource that requires properties for proper setup, # 
# define those properties here. Use name value pairs, separate # 
# the name and value with a semicolon, and separate the   # 
# pairs with commas.           # 
#           # 
# The example shown here is for mysql       # 
#                # 
################################################################# 
#realdatasourceproperties=port;3306,serverName;ibmhost,databaseName;mydb 


################################################################# 
# JNDI DataSource lookup          # 
#                # 
# If you are using the DataSource support outside of an app  # 
# server, you will probably need to define the JNDI Context  # 
# environment.             # 
#                # 
# If the P6Spy code will be executing inside an app server then # 
# do not use these properties, and the DataSource lookup will # 
# use the naming context defined by the app server.    # 
#                # 
# The two standard elements of the naming environment are # 
# jndicontextfactory and jndicontextproviderurl. If you need # 
# additional elements, use the jndicontextcustom property.  # 
# You can define multiple properties in jndicontextcustom,  # 
# in name value pairs. Separate the name and value with a  # 
# semicolon, and separate the pairs with commas.    # 
#                # 
# The example shown here is for a standalone program running on # 
# a machine that is also running JBoss, so the JDNI context  # 
# is configured for JBoss (3.0.4).        # 
#                # 
################################################################# 
#jndicontextfactory=org.jnp.interfaces.NamingContextFactory 
#jndicontextproviderurl=localhost:1099 
#jndicontextcustom=java.naming.factory.url.pkgs;org.jboss.nameing:org.jnp.interfaces 

#jndicontextfactory=com.ibm.websphere.naming.WsnInitialContextFactory 
#jndicontextproviderurl=iiop://localhost:900 

append=true  

,这里是我的连接类:

public class ConnexionBD { 
     private static final ConnexionBD INSTANCE= new ConnexionBD(); 
     private String host; 
     private String database; 
     private int port; 
     private String login; 
     private char[] password; 
     private String privileges; 
     private Connection connection; 
     public static final String DATABASE_JDBC_DRIVER = "com.p6spy.engine.spy.P6SpyDriver"; 

    private ConnexionBD() {} 

    public static ConnexionBD getInstance() { 
     return INSTANCE; 
    } 


    //getters and setters... 

    public Connection getConnection() throws ClassNotFoundException, SQLException { 
     String DATABASE_URL=null; 

     DATABASE_URL = "p6spy:jdbc:oracle:thin:@"+getHost()+":"+getPort()+":"+getDatabase(); 

     if (connection!=null) 
     { 
      return connection ; 
     } 
     else{ 
      Class.forName(DATABASE_JDBC_DRIVER); 

      connection = DriverManager.getConnection(DATABASE_URL,getLogin(),new String(getPassword())) ; 

      return connection ; 
     } 
    } 
    public void setConnection(Connection connection) { 
     this.connection = connection; 
    } 


} 

有人能告诉我这里怎么了? 任何帮助geatly赞赏!

+0

您正在使用哪个版本的p6spy? – quintonm

回答

1

看起来P6SpyDriver在运行时不在您的类路径中。语句Class.forName(DATABASE_JDBC_DRIVER);正在尝试使用加载ConnexionBD的相同类加载器加载P6SpyDriver。无论出于何种原因,该类加载器都无法访问该类。

我建议记录与类加载器及其父母一起注册的URL。这可能会让你对这种情况发生的原因有所了解。有关如何记录类路径位置的示例,请参阅下面的代码。只需将这些方法添加到ConnexionBD类中,并在Class.forName(DATABASE_JDBC_DRIVER);上方立即添加logClassPath(this);即可。

private void logClassPath(final Class clazz) { 
    StringWriter sw = new StringWriter(); 
    PrintWriter pw = new PrintWriter(sw); 
    ClassLoader cl = clazz.getClassLoader(); 
    pw.println("Processing classloader which loaded " + clazz.getName() +" classloader: "+cl.getClass().getName()); 
    if (cl instanceof URLClassLoader) { 
     logUrls(pw, (URLClassLoader) cl); 
    } else { 
     pw.println("Unsupported classloader - " + cl.getClass().getName()); 
    } 
    while (cl.getParent() != null) { 
     cl = cl.getParent(); 
     pw.println("\n\nProcessing parent classloader" +" classloader: "+cl.getClass().getName()); 
     if (cl instanceof URLClassLoader) { 
     logUrls(pw, (URLClassLoader) cl); 
     } else { 
     pw.println("Unsupported classloader - " + cl.getClass().getName()); 
     } 
    } 
    pw.flush(); 
    System.out.print(sw.toString()); 

    } 

    private void logUrls(final PrintWriter pw, final URLClassLoader cl) { 
    if(cl.getURLs().length == 0) { 
     pw.println("No URLs registered for this classloader"); 
    } 
    for (URL url : cl.getURLs()) { 
     pw.println(url.toString()); 
    } 
    } 

我提供的代码只适用于URLClassloader实例的类加载器。它也假定你也有分层类加载器。对于普通的Java应用程序或在轻量级容器中运行的Web应用程序,这应该没问题。

如果您在基于OSGI的容器中运行,那么您将需要使用容器提供的任何工具来解决类加载问题。

+0

谢谢@quintonm,我想出了问题,我没有将正确的jar添加到我的类路径中:)现在P6Spy正在执行,但是没有将日志文件记录到日志文件中,我不知道为什么,我有用我试过的新spy.properties更新了我的问题,我也配置了这个文件,以便P6Spy使用前缀p6spy:与您建议的数据库URL一样[here](http://stackoverflow.com/questions/17749152/ p6spy-not-logging-sql)但仍然无法正常工作:/ – mounaim