写爬虫时经常需要把爬取的数据保存到数据库。
此时,使用原生JDBC时的麻烦是当字段太多时不太容易处理预编译语句中的?。使用mybatis时,同样也得手写sql。而爬取的数据一般是单表或一对多的表,此时完全可以考虑使用Hibernate。
使用Hibernate时就优化考虑使用注解方式的。再使用hbm.xml就有点烦琐了。
单独使用Hibernate(不和Spring集成)时的样板代码如下:
Configuration configure = new Configuration().configure();
sessionFactory = configure.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.getTransaction();
transaction.begin();
// 操作对象来操作数据库
session.save(xxx);
transaction.commit();
session.close();
sessionFactory.close();
待操作的对象需要配置在mapping标签中。mapping支持的属性为 resource/file/jar/package/class
我初次配置hibernate.cfg.xml时,有一配置是
<mapping package="com.example.entity" />
但我在使用的过程中一直未能成功。package不生效,查了资料(sof,想在创建SessionFactory之前检查为什么没有加载)但没找到解决办法。 同样,org.hibernate.cfg.Configuration的addPackage()方法也无效。
尽管上述语句可以使用
<mapping class="com.example.entity.Teacher" />
<mapping class="com.example.entity.Movie" />
...
但有个问题,每爬一个功能就得追加一条配置,有点烦琐。配置文件的功能就应该是配置,配置之后就不应该再被编辑了(以免出错)。
后来,找到了方法。
Configuration还有个方法叫addClass()。它可以添加一个类作为与数据库表的映射。如
configure.addClass(Teacher.class);
与
<mapping class="com.example.entity.Teacher" />
完成的功能相同。
xml配置中不能有循环,但代码中可以使用!反射获取某个包下的类,把它们分别作为Configuration的addClass()方法的参数。
果然可行。
然后样板代码就变成了:
Configuration configure = new Configuration().configure();
// 手动去添加实体类
List<String> classNames = ClazzUtils.getClazzName(Teacher.class.getPackage().getName(), false);
for (String className : classNames) {
configure.addAnnotatedClass(Class.forName(className));
}
sessionFactory = configure.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.getTransaction();
transaction.begin();
session.save(xxx);
transaction.commit();
session.close();
sessionFactory.close();
ClazzUtils类见这里。
需要注意,此时hibernate.cfg.xml中已不再需要配置mapping标签。