<?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <!--声明Hibernate配置文件的开始--> <hibernate-configuration> <!--表明以下的配置是针对session-factory配置的,SessionFactory是Hibernate中的一个类,这个类主要负责保存HIbernate的配置信息,以及对Session的操作--> <session-factory> <!--hibernate.dialect 只是Hibernate使用的数据库方言,就是要用Hibernate连接那种类型的数据库服务器。--> <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> <!--配置数据库的驱动程序,Hibernate在连接数据库时,需要用到数据库的驱动程序--> <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <!--设置数据库的连接url:jdbc:mysql://localhost/hibernate,其中localhost表示mysql服务器名称,此处为本机,hibernate是数据库名--> <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/log</property> <!--连接数据库是用户名--> <property name="hibernate.connection.username">root</property> <!--连接数据库是密码--> <property name="hibernate.connection.password">root</property> <!--数据库连接池的大小--> <property name="hibernate.connection.pool.size">1000</property> <!--是否在后台显示Hibernate用到的SQL语句,开发时设置为true,便于差错,程序运行时可以在Eclipse的控制台显示Hibernate的执行Sql语句。项目部署后可以设置为false,提高运行效率--> <property name="hibernate.show_sql">false</property> <!--jdbc.fetch_size是指Hibernate每次从数据库中取出并放到JDBC的Statement中的记录条数。Fetch Size设的越大,读数据库的次数越少,速度越快,Fetch Size越小,读数据库的次数越多,速度越慢--> <property name="jdbc.fetch_size">50</property> <!--jdbc.batch_size是指Hibernate批量插入,删除和更新时每次操作的记录数。Batch Size越大,批量操作的向数据库发送Sql的次数越少,速度就越快,同样耗用内存就越大--> <property name="jdbc.batch_size">50</property> <!--jdbc.use_scrollable_resultset是否允许Hibernate用JDBC的可滚动的结果集。对分页的结果集。对分页时的设置非常有帮助--> <property name="jdbc.use_scrollable_resultset">false</property> <!--connection.useUnicode连接数据库时是否使用Unicode编码--> <property name="Connection.useUnicode">true</property> <!--connection.characterEncoding连接数据库时数据的传输字符集编码方式,最好设置为gbk,用gb2312有的字符不全--> <property name="connection.characterEncoding">UTF-8</property> <!--指定映射文件为“hibernate/ch1/UserInfo.hbm.xml”--> <mapping resource="com/hjc/backup/entity/LogInfo.hbm.xml" /> </session-factory> </hibernate-configuration>
这里的配置是最基础的配置,没有添加其他任何组件。过段时间我会把使用连接池组件的配置也贴出来。
为了方便以后自己温习,在这里贴出实体类LogInfo.java
package com.hjc.backup.entity; import java.io.Serializable; import com.hjc.backup.bean.Area; public class LogInfo implements Serializable { private static final long serialVersionUID = 1L; private Long id; private String srcIp; private String srcPort; private String desIp; private String desPort; private String mac; private String date; private String content; private Area area; public String getSrcIp() { return srcIp; } public void setSrcIp(String srcIp) { this.srcIp = srcIp; } public String getDesIp() { return desIp; } public void setDesIp(String desIp) { this.desIp = desIp; } public String getMac() { return mac; } public void setMac(String mac) { this.mac = mac; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public String getDate() { return date; } public void setDate(String date) { this.date = date; } public Area getArea() { return area; } public void setArea(Area area) { this.area = area; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getSrcPort() { return srcPort; } public void setSrcPort(String srcPort) { this.srcPort = srcPort; } public String getDesPort() { return desPort; } public void setDesPort(String desPort) { this.desPort = desPort; } }
关联的枚举类Area.java
package com.hjc.backup.bean; import java.io.Serializable; import java.util.NoSuchElementException; public enum Area implements Serializable { XIAOSHAN("xiaoshan"), HUZHOU("huzhou"); private String key; private Area(String key) { this.key = key; } public static Area getArea(String key) { for (Area area : Area.values()) { if (key.equals(area.getKey())) { return area; } } throw new NoSuchElementException(key); } public String getKey() { return key; } }
为了将枚举类型和数据库varchar类型的映射起来,我添加了如下类HibernateVarCharEnum.java
package com.hjc.backup.bean; import java.sql.Types; import java.util.Properties; import org.hibernate.type.EnumType; public class HibernateVarCharEnum extends EnumType { private static final long serialVersionUID = 1L; public void setParameterValues(Properties parameters) { parameters.setProperty(TYPE, "" + Types.VARCHAR); super.setParameterValues(parameters); } }
最后是实体类的映射文件LogInfo.hbm.xml
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.hjc.backup.entity"><!-- 这里的package记得要写对啊。要不然运行也会出错的 --> <class name="LogInfo" table="LogInfo"><!-- 如果表名跟类名一个样的话,那么table属性可以不写 --> <id name="id" type="java.lang.Long"> <column name="id"/> <generator class="native"> </generator> </id> <property name="srcIp"></property> <property name="srcPort"></property> <property name="desIp"></property> <property name="desPort"></property> <property name="mac"></property> <property name="date"></property> <property name="content"></property> <property name="area"> <type name="com.hjc.backup.bean.HibernateVarCharEnum"> <param name="enumClass">com.hjc.backup.bean.Area</param> </type> </property> </class> </hibernate-mapping>
OK了,基本配置就是如此了,下面是测试代码:
DAO层类: HibernateDao.java
package com.hjc.backup.dao.hibernate; import java.sql.SQLException; import java.util.List; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import com.hjc.backup.bean.Area; import com.hjc.backup.entity.LogInfo; public class HibernateDao { private static Configuration configuration = new Configuration().configure(); public SessionFactory getSessionFactory() { return configuration.buildSessionFactory(); } public void closeSessionFactory(SessionFactory sessionFactory) { if (sessionFactory != null) { sessionFactory.close(); } } public boolean getByLogInfo(String srcIp, String desIp, long startTimestamp, long endTimestamp, Area area) throws SQLException { String sql = "from LogInfo l where l.srcIp = ? and l.desIp = ? and unix_timestamp(l.date) >= ? and unix_timestamp(l.date) < ? and l.area = ?"; SessionFactory sessionFactory = getSessionFactory(); Session session = sessionFactory.openSession(); Transaction tr = session.beginTransaction(); Query query = session.createQuery(sql) .setString(0, srcIp) .setString(1, desIp) .setLong(2, startTimestamp) .setLong(3, endTimestamp) .setString(4, area.getKey()) ; @SuppressWarnings("unchecked") List<LogInfo> logInfos = query.list(); tr.commit(); session.close(); closeSessionFactory(sessionFactory); return logInfos.isEmpty() ? true : false; } public boolean saveLogoInfo(LogInfo logInfo) throws SQLException { SessionFactory sessionFactory = getSessionFactory(); Session session = sessionFactory.openSession(); Transaction tr = session.beginTransaction(); Long result = (Long) session.save(logInfo); tr.commit(); session.close(); closeSessionFactory(sessionFactory); return result == 0 ? false : true; } }
测试类: LogService.java
package com.hjc.backup.service; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import java.sql.SQLException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.List; import com.hjc.backup.bean.Area; import com.hjc.backup.dao.hibernate.HibernateDao; import com.hjc.backup.entity.LogInfo; public class LogService { private static HibernateDao hibernateDao = new HibernateDao(); public void saveLogFiles() throws ClassNotFoundException, SQLException, IOException{ Long count = 0L; BufferedReader br = null; String syslogPath = "D:\\syslog"; File syslog = new File(syslogPath); for (String dayFileName : syslog.list()) { String daFilePath = syslogPath + "\\" + dayFileName; File dayFile = new File(daFilePath); if (dayFile.isFile()) { continue; } for (String logFileName : dayFile.list()) { String logFilePath = syslogPath + "\\" + dayFileName + "\\" + logFileName; System.out.println("正在分析日志: " + logFilePath); File logFile = new File(logFilePath); try { // 设置读取格式 br = new BufferedReader(new InputStreamReader(new FileInputStream(logFile), "GBK")); String line = ""; while ((line = br.readLine()) != null) { line = new String(line.getBytes(), "UTF-8"); int indexOfLen = line.indexOf("len"); int indexOfFrom = line.indexOf("from"); if (indexOfLen == -1 || indexOfFrom == -1) { continue; } String srcIpAndPort = getSrcIpAndPortFromLog(line); String srcIp = srcIpAndPort.split(":")[0]; String srcPort = srcIpAndPort.split(":")[1]; String desIpAndPort = getDesIpAndPortFromLog(line); String desIp = desIpAndPort.split(":")[0]; String desPort = desIpAndPort.split(":")[1]; String date = getDateFromLog(line, indexOfLen, indexOfFrom); String startDate = getStartDateFromLog(line, indexOfLen, indexOfFrom); // 计算当天零点 // 11.21: 1384963200 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); long startTimeInMillis = sdf.parse(startDate).getTime(); long startTime = sdf.parse(startDate).getTime() / 1000; // 计算明天零点 // 11.22: 1385049600 Calendar cal = Calendar.getInstance(); cal.setTimeInMillis(startTimeInMillis); cal.set(Calendar.DATE, cal.get(Calendar.DATE) +1); long endTime = cal.getTimeInMillis() / 1000; String mac = getMacFromLog(line); boolean result = hibernateDao.getByLogInfo(srcIp, desIp, startTime, endTime, Area.XIAOSHAN); if (!result) { System.out.println("repeat log count: " + ++count + "; the content is " + line); continue; } LogInfo logInfo = new LogInfo(); logInfo.setMac(mac); logInfo.setSrcIp(srcIp); logInfo.setSrcPort(srcPort); logInfo.setDesIp(desIp); logInfo.setDesPort(desPort); logInfo.setDate(date); logInfo.setContent(line); logInfo.setArea(Area.XIAOSHAN); hibernateDao.saveLogoInfo(logInfo); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (ParseException e) { e.printStackTrace(); } } } } /** * 写入文本 */ public void writeLogInfoToTxt(List<LogInfo> logInfoList) throws IOException { File LogInfo = null; FileWriter fw = null; BufferedWriter bw = null; try { LogInfo = new File("D:\\syslog\\logInfo.txt"); if (!LogInfo.exists()) { LogInfo.createNewFile(); } fw = new FileWriter(LogInfo); bw = new BufferedWriter(fw); for (LogInfo logInfo : logInfoList) { bw.write("srcIP: " + logInfo.getSrcIp() + "\t\tdestIP: " + logInfo.getDesIp() + "\t\tMAC: " + logInfo.getMac() + "\t\tdate: " + logInfo.getDate()); bw.newLine(); } } catch (IOException e) { e.printStackTrace(); } finally { if (bw != null) { bw.close(); } if (fw != null) { fw.close(); } } } /** * 从一行日志记录中获取源IP和端口号 */ private String getSrcIpAndPortFromLog(String line) { String[] preLog = line.split("->")[0].split(","); String ipAndPort = preLog[preLog.length - 1]; String srcIpAndPort = ipAndPort.substring(1, ipAndPort.length() - 1); return srcIpAndPort; } /** * 从一行日志记录中获取目标IP和端口号 */ private String getDesIpAndPortFromLog(String line) { String[] preLog = line.split("->")[1].split(","); String destIpAndPort = preLog[0]; return destIpAndPort; } /** * 从一行日志记录中获取MAC地址 */ private String getMacFromLog(String line) { int indexOfMac = line.indexOf("src-mac"); String mac = line.substring(indexOfMac + 8, indexOfMac + 25); return mac; } /** * 从一行日志记录中获取日期时间 */ public String getDateFromLog(String line, int indexOfLen, int indexOfFrom) throws ParseException { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String dateOfLog = line.substring(indexOfLen, indexOfFrom); int year = 2013; int month = parseMonthType(dateOfLog.split(" ")[3].split("-")[1]); int day = Integer.parseInt(dateOfLog.split(" ")[3].split("-")[0]); String date = year + "-" + month + "-" + day + " " + dateOfLog.split(" ")[4]; return sdf.format(sdf.parse(date)); } /** * 从一行日志记录中获取当天零点 */ public String getStartDateFromLog(String line, int indexOfLen, int indexOfFrom) throws ParseException { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); String dateOfLog = line.substring(indexOfLen, indexOfFrom); int year = 2013; int month = parseMonthType(dateOfLog.split(" ")[3].split("-")[1]); int day = Integer.parseInt(dateOfLog.split(" ")[3].split("-")[0]); String date = year + "-" + month + "-" + day; return sdf.format(sdf.parse(date)); } /** * 转换记录中的月份 */ public int parseMonthType(String month) { int monthOfNum = 0; if ("Jan".equalsIgnoreCase(month)) { monthOfNum = 1; } else if ("Feb".equalsIgnoreCase(month)) { monthOfNum = 2; } else if ("Mar".equalsIgnoreCase(month)) { monthOfNum = 3; } else if ("Apr".equalsIgnoreCase(month)) { monthOfNum = 4; } else if ("May".equalsIgnoreCase(month)) { monthOfNum = 5; } else if ("Jun".equalsIgnoreCase(month)) { monthOfNum = 6; } else if ("Jul".equalsIgnoreCase(month)) { monthOfNum = 7; } else if ("Aug".equalsIgnoreCase(month)) { monthOfNum = 8; } else if ("Sep".equalsIgnoreCase(month)) { monthOfNum = 9; } else if ("Oct".equalsIgnoreCase(month)) { monthOfNum = 10; } else if ("Nov".equalsIgnoreCase(month)) { monthOfNum = 11; } else if ("Dec".equalsIgnoreCase(month)) { monthOfNum = 12; } return monthOfNum; } /** * 测试类 */ public static void main(String[] args) { LogService filesUtils = new LogService(); try { System.out.println("开始备份"); filesUtils.saveLogFiles(); System.out.println("结束备份"); } catch (IOException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } }
该套代码还不够完善,存在的问题主要是: 程序一跑起来就会对数据库频繁的操作(大概分析到4000条记录),从而导致如下异常:
Exception in thread "main" org.hibernate.exception.JDBCConnectionException: Cannot open connection at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:99) at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66) at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:52) at org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:449) at org.hibernate.jdbc.ConnectionManager.getConnection(ConnectionManager.java:167) at org.hibernate.jdbc.JDBCContext.connection(JDBCContext.java:160) at org.hibernate.transaction.JDBCTransaction.begin(JDBCTransaction.java:81) at org.hibernate.impl.SessionImpl.beginTransaction(SessionImpl.java:1473) at com.hjc.backup.dao.hibernate.HibernateDao.getByLogInfo(HibernateDao.java:38) at com.hjc.backup.service.LogService.saveLogFiles(LogService.java:85) at com.hjc.backup.service.LogService.main(LogService.java:277) Caused by: com.mysql.jdbc.CommunicationsException: The driver was unable to create a connection due to an inability to establish the client portion of a socket. This is usually caused by a limit on the number of sockets imposed by the operating system. This limit is usually configurable. For Unix-based platforms, see the manual page for the 'ulimit' command. Kernel or system reconfiguration may also be required. For Windows-based platforms, see Microsoft Knowledge Base Article 196271 (Q196271). at com.mysql.jdbc.Connection.createNewIO(Connection.java:2847) at com.mysql.jdbc.Connection.<init>(Connection.java:1555) at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:285) at java.sql.DriverManager.getConnection(Unknown Source) at java.sql.DriverManager.getConnection(Unknown Source) at org.hibernate.connection.DriverManagerConnectionProvider.getConnection(DriverManagerConnectionProvider.java:133) at org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:446) ... 7 more
楼主对这个异常实在有点拙计,改天配个连接池看看能不能解决。
好了,就到这里了。
2013-12-28 17:56:20