p6spy使用小结
2017-07-14 10:31
239 查看
在之前的hibernate的总结中,遇到一个小问题,那就是打印sql语句的问题.在上个hibernate项目的基础上(spring+hibernate),继续p6spy的学习(p6spy相关文件下载)
hibernate控制sql语句的参数配置:
通过一个个connection完成对具体数据的操作.
从上例中可知,使用connection进行操作时摒弃了statement,而使用PreparedStatement,statement采用硬编码,每次执行sql都会进行编译,效率低,同时还能带来sql注入等不安全因素,而PreparedStatement相当于动态sql,对于相同的sql只会编译一次,参数通过注入的方式,有效阻止的sql注入,因此,项目中大多时候选择的是PreparedStatement,但对于那些一次性操作的,比如批量插入,删除等,可以直接使用statement.
hibernate默认使用的PreparedStatement,其取格式的sql是预编译的sql(参数没有被完全注入进来),从而会有一系列的?,要显示思路一种就是改变取sql的时机,等参数全部注入完成再取(p6spy),一种就是利用log,将传入的参数打印出来(这样sql,与参数分离),显然后一种没有前一种方便(hibernate打印sql)
p6spy使用com.p6spy.engine.spy.P6SpyDriver作为数据库驱动,P6SpyDriver是对原生原生驱动(此处以com.mysql.jdbc.Driver为例)的封装,其对数据的操作还是调用原生驱动的方法,只是多了sql监控的功能.
paspy基本使用.
配置驱动
自定义输出内容格式:
hibernate控制sql语句的参数配置:
<!--开发调试使用 --> <!--控制台打印sql语句 --> <prop key="hibernate.show_sql">false</prop> <!--格式化语句 --> <prop key="hibernate.format_sql">false</prop> <!--如果开启, Hibernate将在SQL中生成有助于调试的注释信息, 默认值为false --> <prop key="hibernate.use_sql_comments">false</prop>但是这样有个问题,那就是hibernate中打印的参数都是一些?,实际上hibernate打印都是一些预编译的sql,无法打印真正的sql.回顾一些jdbc(java使用连接数据的api,Java DataBase Connectivity)直连数据库
Connection conn = null; try { // 第一步,注册驱动程序 以mysql驱动为例 Class.forName("com.mysql.jdbc.Driver"); // 第二步,获取一个数据库的连接 conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "123"); conn.setAutoCommit(false); // 第三步,创建一个会话 //Statement stmt = conn.createStatement(); String sql = "select * from school s where s.id=?"; PreparedStatement stmt = conn.prepareStatement(sql); stmt.setInt(1, 1); // 第四步,执行SQL语句,增加,删除,修改记录 或者查询记录 // stmt.executeUpdate(); ResultSet rs = stmt.executeQuery(); ResultSetMetaData m = rs.getMetaData(); // 第五步,对查询的结果进行处理 int columns = m.getColumnCount(); // 显示列,表格的表头 for (int i = 1; i <= columns; i++) { System.out.print(m.getColumnName(i)); System.out.print("\t\t"); } System.out.println(); // 显示表格内容 while (rs.next()) { for (int i = 1; i <= columns; i++) { System.out.print(rs.getString(i)); System.out.print("\t\t"); } System.out.println(); } // 第六步,关闭连接 conn.commit(); rs.close(); stmt.close(); } catch (Exception e) { e.printStackTrace(); System.out.println("进行回滚操作"); conn.rollback(); } finally { conn.close(); }而我们通常配置的数据库驱动实现了与数据库的交互的前提,数据库连接池如druid,dbcp,c3p0,jboss datasource,bonecp,proxool等则管理通数据具体操作的连接connection,
通过一个个connection完成对具体数据的操作.
从上例中可知,使用connection进行操作时摒弃了statement,而使用PreparedStatement,statement采用硬编码,每次执行sql都会进行编译,效率低,同时还能带来sql注入等不安全因素,而PreparedStatement相当于动态sql,对于相同的sql只会编译一次,参数通过注入的方式,有效阻止的sql注入,因此,项目中大多时候选择的是PreparedStatement,但对于那些一次性操作的,比如批量插入,删除等,可以直接使用statement.
hibernate默认使用的PreparedStatement,其取格式的sql是预编译的sql(参数没有被完全注入进来),从而会有一系列的?,要显示思路一种就是改变取sql的时机,等参数全部注入完成再取(p6spy),一种就是利用log,将传入的参数打印出来(这样sql,与参数分离),显然后一种没有前一种方便(hibernate打印sql)
p6spy使用com.p6spy.engine.spy.P6SpyDriver作为数据库驱动,P6SpyDriver是对原生原生驱动(此处以com.mysql.jdbc.Driver为例)的封装,其对数据的操作还是调用原生驱动的方法,只是多了sql监控的功能.
paspy基本使用.
配置驱动
<!--设置数据库连接 --> <property name="driverClass" value="com.p6spy.engine.spy.P6SpyDriver" />数据库连接(多了一个p6spy):
db.jdbcUrl = jdbc:p6spy:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&rewriteBatchedStatements=truespy.propertie
#配置输出方式 #appender=com.p6spy.engine.spy.appender.Slf4JLogger #appender=com.p6spy.engine.spy.appender.FileLogger appender=com.p6spy.engine.spy.appender.StdoutLogger #配置输出内容格式(此处自定义) #默认 com.p6spy.engine.spy.appender.SingleLineFormat logMessageFormat=spring.redis.test.util.MySingleLineFormat #输出内容选择 #list of categories to exclude: error, info, batch, debug, statement, #commit, rollback and result are valid values # 4000 (default is info,debug,result,resultset,batch) excludecategories=info,batch,debug,commit,rollback,result,resultset此处为了测试方便,使用控制台打印,自定义输出格式,输出内容选择statement
自定义输出内容格式:
package spring.redis.test.util; import org.hibernate.engine.jdbc.internal.BasicFormatterImpl; import com.p6spy.engine.spy.appender.SingleLineFormat; public class MySingleLineFormat extends SingleLineFormat { private final static BasicFormatterImpl sqlformat = new BasicFormatterImpl(); /** * Formats a log message for the logging module * * @param connectionId the id of the connection * @param now the current ime expressing in milliseconds * @param elapsed the time in milliseconds that the operation took to complete * @param category the category of the operation * @param prepared the SQL statement with all bind variables replaced with actual values * @param sql the sql statement executed * @return the formatted log message */ @Override public String formatMessage(final int connectionId, final String now, final long elapsed, final String category, final String prepared, final String sql) { return "#token time:" + elapsed + "ms | category:" + category + " | connectionId: " + connectionId + "\n" + "预编译语句"+sqlformat.format(prepared) + "\nread sql" + sqlformat.format(sql) } }这是使用了hibernate格式化类,BasicFormatterImpl,以上展示的参数都是可以展示,测试打印
//执行打印sql hibernateTemplate.get(School.class, 1); /* #token time:3ms | category:statement | connectionId: 2 预编译语句 select school0_.id as id1_1_0_, school0_.create_time as create_t2_1_0_, school0_.des as des3_1_0_, school0_.name as name4_1_0_, school0_.update_time as update_t5_1_0_ from school school0_ where school0_.id=? read sql select school0_.id as id1_1_0_, school0_.create_time as create_t2_1_0_, school0_.des as des3_1_0_, school0_.name as name4_1_0_, school0_.update_time as update_t5_1_0_ from school school0_ where school0_.id=1*/
相关文章推荐
- DBGrideh使用小结(一)
- 创建,测试和使用Web服务的小结
- TChart使用经验小结
- treeview的使用小结
- C# OleDbCommand 和 OleDbDataReader 使用小结
- vi编辑器的学习使用(小结)
- P6SPY的安装和使用
- SQL SERVER SQL Agent服务使用技巧小结
- SQL SERVER SQL Agent服务使用技巧小结[转]
- XML文档搜索使用小结
- 使用弹出窗口的技巧小结
- Web Services 中 Web Method 的使用小结(一)
- TestDirector安装使用过程小结
- Ant使用小结
- jbuilder8开发环境使用小结
- SQL Server 最佳实践分析器使用小结
- 在JAVA中使用文档对象模型DOM经验小结[转载]
- ASP.NET中TreeView控件使用小结
- UrlReWriter 使用经验小结
- c#.NET使用小结(1)