hibernate实现动态表查询的多种解决方案

[size=large]hibernate实现动态表查询的多种解决方案.[/size]
[size=medium]方案1.[/size]就是写一个继承自NamingStrategy的类,然后把这个类加到hibernate的配制文件中去.

测试例子如下,很容易就成功了,关键在于把配制加到hibernate的配制文件的正确位置.有加载了就能正常运行.
但据试验,这个办法还存在一些问题.这个动态表不是真正的动态表,而是一个别名.因为在实践的运行中都有框架的么.总不可能为了实现一个动态表再重新初

始化一次,那个类这个方案用来做别名还是可以的,算不上真正的动态表.反正我没有找到比较成功的动态加载的办法.

有结论说:这个NamingStrategy类会在项目启动时加载.应该是spring 实例化bean时搞的,一次实例化,就不在创建新实例了,

好像spring的LocalSessionFactoryBean在创建时会将xml与pojo的映射关系放到map里面,在生成这种映射关系时会调tableName方法,此后再取表名的时候就

不用tableName方法了,至于表名具体怎么取的,我就不懂了,源码看着晕.


Teacher类:

view plaincopy to clipboardprint?package org.zxy.model;
import java.util.Date;
import javax.persistence.Basic;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
@Entity
public class Teacher {
private int id;
private String name;
private String title;
private Date birthday;
@Basic
@Temporal(TemporalType.TIME)
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
@Id
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Basic
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
package org.zxy.model;
import java.util.Date;
import javax.persistence.Basic;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
@Entity
public class Teacher {
private int id;
private String name;
private String title;
private Date birthday;
@Basic
@Temporal(TemporalType.TIME)
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
@Id
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Basic
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}


Student类:

view plaincopy to clipboardprint?package org.zxy.model;
import java.util.Date;
public class Student {
private String id;
private String name;
private int age;
private Date birthday;
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public Student() {
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
package org.zxy.model;
import java.util.Date;
public class Student {
private String id;
private String name;
private int age;
private Date birthday;
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public Student() {
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}


用JUnit测试:

TeacherTest:

view plaincopy to clipboardprint?package org.zxy.model;
import java.util.Date;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
public class TeacherTest {
private static SessionFactory sf = null;
@BeforeClass
public static void beforeClass() {
sf = new AnnotationConfiguration().configure().buildSessionFactory();
}
@Test
public void save(){
Teacher t = new Teacher();
t.setId(4);
t.setName("zhangsan");
t.setTitle("chuji");
t.setBirthday(new Date());
Session session = sf.openSession();
session.beginTransaction();
session.save(t);
session.getTransaction().commit();
session.close();
}
@AfterClass
public static void afterClass() {
sf.close();
}
}
package org.zxy.model;
import java.util.Date;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
public class TeacherTest {
private static SessionFactory sf = null;
@BeforeClass
public static void beforeClass() {
sf = new AnnotationConfiguration().configure().buildSessionFactory();
}
@Test
public void save(){
Teacher t = new Teacher();
t.setId(4);
t.setName("zhangsan");
t.setTitle("chuji");
t.setBirthday(new Date());
Session session = sf.openSession();
session.beginTransaction();
session.save(t);
session.getTransaction().commit();
session.close();
}
@AfterClass
public static void afterClass() {
sf.close();
}
}


StudentTest:

view plaincopy to clipboardprint?package org.zxy.model;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
public class StudentTest {
public static SessionFactory sf = null;
@BeforeClass
public static void beforeClass() {
sf = new Configuration().configure().buildSessionFactory();
}
@Test
public void save() {
Student stu = new Student();
stu.setName("wangwu");
stu.setAge(4);
Session session = sf.openSession();
session.beginTransaction();
session.save(stu);
session.getTransaction().commit();
session.close();
}
@AfterClass
public static void afterClass() {
sf.close();
}
}
package org.zxy.model;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
public class StudentTest {
public static SessionFactory sf = null;
@BeforeClass
public static void beforeClass() {
sf = new Configuration().configure().buildSessionFactory();
}
@Test
public void save() {
Student stu = new Student();
stu.setName("wangwu");
stu.setAge(4);
Session session = sf.openSession();
session.beginTransaction();
session.save(stu);
session.getTransaction().commit();
session.close();
}
@AfterClass
public static void afterClass() {
sf.close();
}
}


hibernate.cfg.xml:

view plaincopy to clipboardprint?<?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-configuration>
<session-factory>
<!-- Database connection settings -->
<property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<property name="connection.url">jdbc:oracle:thin:@localhost:1521:zxy</property>
<property name="connection.username">scott</property>
<property name="connection.password">tiger</property>
<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">1</property>
<!-- SQL dialect -->
<property name="dialect">org.hibernate.dialect.OracleDialect</property>
<!-- Enable Hibernate's automatic session context management -->
<property name="current_session_context_class">thread</property>
<!-- Disable the second-level cache -->
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<!-- Echo all executed SQL to stdout -->
<property name="show_sql">true</property>
<property name="format_sql">true</property>
<!-- Drop and re-create the database schema on startup -->
<property name="hbm2ddl.auto">update</property>
<mapping resource="org/zxy/model/Student.hbm.xml"/>
<mapping class="org.zxy.model.Teacher"/>
<mapping class="org.zxy.model.Person"/>
</session-factory>
</hibernate-configuration>
<?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-configuration>
<session-factory>
<!-- Database connection settings -->
<property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<property name="connection.url">jdbc:oracle:thin:@localhost:1521:zxy</property>
<property name="connection.username">scott</property>
<property name="connection.password">tiger</property>
<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">1</property>
<!-- SQL dialect -->
<property name="dialect">org.hibernate.dialect.OracleDialect</property>
<!-- Enable Hibernate's automatic session context management -->
<property name="current_session_context_class">thread</property>
<!-- Disable the second-level cache -->
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<!-- Echo all executed SQL to stdout -->
<property name="show_sql">true</property>
<property name="format_sql">true</property>
<!-- Drop and re-create the database schema on startup -->
<property name="hbm2ddl.auto">update</property>
<mapping resource="org/zxy/model/Student.hbm.xml"/>
<mapping class="org.zxy.model.Teacher"/>
<mapping class="org.zxy.model.Person"/>
</session-factory>
</hibernate-configuration>

测试StudentTest时,会出现new Configuration()得不到值,出现空指针

改为AnnotationConfiguration()即刻解决问题


[size=medium]方案2 hibernate--拦截器[/size]
也就是在hibernate生成sql语句之后把我们要用的动太表名加入到sql中去.这个办法是可行的.用个字符串替换的办法就可以.很简

单吧.不过还有点麻烦,又要多写个类.不过总算是个办法.例子如下,也是找的.看着自己改到项目中去吧.


hibernate--拦截器

在Hibernate的拦截器要不要使用需要看你的需求..一般来说, 是在你操作某张表的时候附带要操作其他的表..而这个操作不是正常性操作,就是你平常不需要

执行这个操作.只是偶尔的操作..通俗点解释就是

比如,你有一个系统,是超市购物系统.这个系统是hibernate来做数据表的持久化.那么,如果你有一个需求,比如在节假日的时候,所有会员的购物积分翻三倍.

这个时候,当然你可以再写一个操作类,表示的是操作三倍积分的,但是你这样做很明显是不合理的,我们可以通过添加拦截器的方法解决这个问题.(这个例子可

能有些不合理,但是至少说明了问题)

看下面的步骤

1 创建一个工程,添加hibernate的支持...这个可以用myeclipse自动帮你完成.说了很多了,反正所以hibernate的操作都必须有这个步骤.

2 创建一个拦截器类...他继承了org.hibernate.Interceptor这个接口.看下面的代码

拦截器接口一共有十八个方法,对应了hibernate操作表的十八种状态,那些我知道的我都有打印注释了.

package com.test.interceptor;

import java.io.Serializable;
import java.util.Iterator;

import org.hibernate.CallbackException;
import org.hibernate.EntityMode;
import org.hibernate.Interceptor;
import org.hibernate.Transaction;
import org.hibernate.type.Type;

/**
* @author 陈静波 E-mail:jingbo2759@163.com
* @version 创建时间:Sep 24, 2009 4:21:56 PM
* 类说明
*/
public class MyInterceptor implements Interceptor
{

@Override
public void afterTransactionBegin(Transaction arg0)
{
//开始事务之后被执行
System.out.println("事务开始了");
}

@Override
public void afterTransactionCompletion(Transaction arg0)
{
//结束事务的时候被执行
System.out.println("事务结束了");
}

@Override
public void beforeTransactionCompletion(Transaction arg0)
{
//事务完成之前
System.out.println("事务完成之前");
}

@Override
public int[] findDirty(Object arg0, Serializable arg1, Object[] arg2,
Object[] arg3, String[] arg4, Type[] arg5)
{
System.out.println("找到脏对象的时候");
return null;
}

@Override
public Object getEntity(String arg0, Serializable arg1)
throws CallbackException
{
System.out.println("获得对象的时候");
return null;
}

@Override
public String getEntityName(Object arg0) throws CallbackException
{
System.out.println("获得对象名的时候");
return null;
}

@Override
public Object instantiate(String arg0, EntityMode arg1, Serializable arg2)
throws CallbackException
{
System.out.println("初始化对象的时候");
return null;
}

@Override
public Boolean isTransient(Object arg0)
{
// TODO Auto-generated method stub
return null;
}

@Override
public void onCollectionRecreate(Object arg0, Serializable arg1)
throws CallbackException
{
}

@Override
public void onCollectionRemove(Object arg0, Serializable arg1)
throws CallbackException
{
System.out.println("容器被移除的时候,就是表中的set");
}

@Override
public void onCollectionUpdate(Object arg0, Serializable arg1)
throws CallbackException
{
System.out.println("容器被更新的时候");
}

@Override
public void onDelete(Object arg0, Serializable arg1, Object[] arg2,
String[] arg3, Type[] arg4) throws CallbackException
{
System.out.println("执行删除操作的时候");
}

@Override
public boolean onFlushDirty(Object arg0, Serializable arg1, Object[] arg2,
Object[] arg3, String[] arg4, Type[] arg5) throws CallbackException
{
return false;
}

@Override
public boolean onLoad(Object arg0, Serializable arg1, Object[] arg2,
String[] arg3, Type[] arg4) throws CallbackException
{
System.out.println("载入的时候");
return false;
}

@Override
public String onPrepareStatement(String arg0)
{
System.out.println("执行操作的时候.任何增删改查操作都可以");
return arg0;
}

@Override
public boolean onSave(Object arg0, Serializable arg1, Object[] arg2,
String[] arg3, Type[] arg4) throws CallbackException
{
System.out.println("执行保存操作的时候");
return false;
}

@Override
public void postFlush(Iterator arg0) throws CallbackException
{

}

@Override
public void preFlush(Iterator arg0) throws CallbackException
{
// TODO Auto-generated method stub

}

}

3 拦截器类创建好了以后,我们需要将拦截器添加到session里面.添加的办法修改HibernateSessionFactory类...下面红字的是Myeclipse自动生成的代码以后

添加的代码

package com.util;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.cfg.Configuration;

import com.test.interceptor.MyInterceptor;

/**
* Configures and provides access to Hibernate sessions, tied to the
* current thread of execution. Follows the Thread Local Session
* pattern, see {@link http://hibernate.org/42.html }.
*/
public class HibernateSessionFactory {

/**
* Location of hibernate.cfg.xml file.
* Location should be on the classpath as Hibernate uses
* #resourceAsStream style lookup for its configuration file.
* The default classpath location of the hibernate config file is
* in the default package. Use #setConfigFile() to update
* the location of the configuration file for the current session.
*/
private static String CONFIG_FILE_LOCATION = "/hibernate.cfg.xml";
private static final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();
private static Configuration configuration = new Configuration();
private static org.hibernate.SessionFactory sessionFactory;
private static String configFile = CONFIG_FILE_LOCATION;
private static MyInterceptor my = new MyInterceptor();

static {
try {
configuration.configure(configFile);
sessionFactory = configuration.buildSessionFactory();
} catch (Exception e) {
System.err
.println("%%%% Error Creating SessionFactory %%%%");
e.printStackTrace();
}
}
private HibernateSessionFactory() {
}

/**
* Returns the ThreadLocal Session instance. Lazy initialize
* the <code>SessionFactory</code> if needed.
*
* @return Session
* @throws HibernateException
*/
public static Session getSession() throws HibernateException {
Session session = (Session) threadLocal.get();

if (session == null || !session.isOpen()) {
if (sessionFactory == null) {
rebuildSessionFactory();
}
session = (sessionFactory != null) ? sessionFactory.openSession(my)
: null;
threadLocal.set(session);
}

return session;
}

/**
* Rebuild hibernate session factory
*
*/
public static void rebuildSessionFactory() {
try {
configuration.configure(configFile);
sessionFactory = configuration.buildSessionFactory();
} catch (Exception e) {
System.err
.println("%%%% Error Creating SessionFactory %%%%");
e.printStackTrace();
}
}

/**
* Close the single hibernate session instance.
*
* @throws HibernateException
*/
public static void closeSession() throws HibernateException {
Session session = (Session) threadLocal.get();
threadLocal.set(null);

if (session != null) {
session.close();
}
}

/**
* return session factory
*
*/
public static org.hibernate.SessionFactory getSessionFactory() {
return sessionFactory;
}

/**
* return session factory
*
* session factory will be rebuilded in the next call
*/
public static void setConfigFile(String configFile) {
HibernateSessionFactory.configFile = configFile;
sessionFactory = null;
}

/**
* return hibernate configuration
*
*/
public static Configuration getConfiguration() {
return configuration;
}

}

4 创建一个user表.


create table `user`.`user`(
`id` INT not null,
`username` CHAR(50) not null,
`age` INT not null,
primary key (`id`)
);

create unique index `PRIMARY` on `user`.`user`(`id`);

5 生成对应的实体类和hbm.xml文件(这个代码就不放上来了)

6 写测试代码

package com.test.main;

import org.hibernate.Session;
import org.hibernate.Transaction;

import com.test.model.User;
import com.util.HibernateSessionFactory;

/**
* @author 陈静波 E-mail:jingbo2759@163.com
* @version 创建时间:Sep 24, 2009 4:32:08 PM
* 类说明
*/
public class UserTest
{

public static void main(String[] args)
{
Session session = HibernateSessionFactory.getSession();
Transaction tx = session.beginTransaction();
User user = new User();
user.setId(1);
user.setUsername("abc");
user.setAge(10);

session.saveOrUpdate(user);
tx.commit();
session.close();

}

}
可以看最后打印出来的内容是

事务开始了
获得对象名的时候
执行操作的时候.任何增删改查操作都可以
Hibernate: select user_.id, user_.username as username6_, user_.age as age6_ from user.user user_ where user_.id=?
获得对象名的时候
执行保存操作的时候
找到脏对象的时候
执行操作的时候.任何增删改查操作都可以
执行操作的时候.任何增删改查操作都可以
Hibernate: insert into user.user (username, age, id) values (?, ?, ?)
事务完成之前
事务结束了


[size=medium]方案3. [/size]

其实前面的方法用起来还是有那么点一点不爽,不过每个人的开发环境不一样,框架不一样,准就会用呢,呵呵.
所以又回到了hql上.还是这个办法最简单.
取得hibernate的session.然后调用createSQLQuery方法然后再把参数加进去.问题解决了...这个例子是我自己的.当然了这个简单一些.
例子如下

public List findList(){
Query query = this.getASession().createSQLQuery("select {SysUser.*} from sysuser123 {SysUser}").addEntity("SysUser", SysUser.class);
return query.list();
}
说明,{SysUser}是实体原形,也是动太表的原型了,后面就是参数了,用起来很容易不是么.我喜欢这个方案.getASession()得到一个hibernate下的session
最简单的方案了.哈哈.


[size=medium]方案4.[/size]

勤劳的人用的方法,自己写sql实现,当然了破坏了Hibernate千方百计实现的面向对向的数据库查询不是么,不过也算是一个最最灵活的方法了.
也算是个法子,网上找来的例子如下.

在实际项目的开发中,有时需要操作动态表的数据。假设当前所开发的系统需要通过数据库记录系统的日志信息,由于日志信息数据量庞大,所以为了高效了

记录和查询,每个月动态产生一个保存日志的信息表,表名包含表示年月的字符串。例如,2009年2月的日志信息保存在log200902这个表中,log200903表示

2009年3月的日志信息数据。以此类推,这些表均用于保存日志数据,其中表中的字段和结构是相同的,只是表名不同。

在Hibernate中提供的持久化类与数据表的映射基本都是一个持久化类映射一个表。程序运行的过程中很难动态修改一个映射文件中的表名,实现一个持久化

类动态地映射不同的表。通过SQLQuery对象即可以实现Hibernate对动态表的映射。

我在实际的项目应用中,有时会设计出这样的一种数据表,每个时间段产生一个新表,例如是按年或月或日。相同类型的表中,所有的字段结构都是一样的。

而 hibernate 提供的类与表的映射,是只能映射到一个具体表的,在程序的运行过程中,很难去动态修改一个 hbm 对应的表名。我在网上也有看到一实现,

但是很复杂,并且不符合我的要求。

因此我就想到直接用 jdbc 去操作数据库,这样的做法是绕过 hibernate 了。方法是从 hibernate 的 session 中,直接取得数据库 connection ,然后就

直接 jdbc 了。

后来在升级了 proxool 到 9.0RC3 后,发现居然出现了数据库连接无法释放的问题。为了解决这个问题,我查阅了 hibernate doc。我发现原来用 SQLQuery

可以更好的解决,并且可以重新用于 hibernate hbm 机制。以下举例说明。

例如我有一个 pojo 是 ReadInfo,用来记录阅读信息的。由于数据量宠大,所以我的思路是按月划分,每个月一张表。所以只是表名不同,而字段是完全相

同的。

ReadInfo.java 是这样的,其中 userId, year, month, day 是联合主键:

private Integer userId;
private Integer year;
private Integer month;
private Integer day;
private Integer point;


那么相应的 ReadInfo.hbm.xml 的片段是

<class name="ReadInfo" table="tblReadInfo" mutable="false">
<composite-id>
<key-property name="userId" column="userId" type="integer"/>
<key-property name="year" column="year" type="integer"/>
<key-property name="month" column="month" type="integer"/>
<key-property name="day" column="day" type="integer"/>
</composite-id>
<property name="point" column="point" type="integer"/>
</class>


上面的xml,注意 2 个细节

1. pojo 所映射的 table tblReadInfo 实际上是不存在的。实际的表是 tblRead200710 之类的;

2. mutable 要设置为 false,即是说,关闭 hibernate 对这个 pojo 的任何持久化操作,以避免 hibernate 把数据写到 tblReadInfo 中(这个表是不存在

的嘛)。因此,所有的持久化操作,都是需要自己通过 SQLQuery 来处理。

现在可以看一下 ado 中的操作了,先看一个 select 操作

public ReadInfo selectReadInfo(Integer userId, Integer year,
Integer month, Integer day) throws HibernateException
{
ReadInfo readInfo = null;

Session session = getSession();
Transaction tx = session.beginTransaction();

try
{
String sql = "select * from tblRead"
+ Misc.formatMoon(year, month)
+ " where userId=? and day=?";

SQLQuery query = session.createSQLQuery(sql);
query.addEntity(ReadInfo.class);

query.setLong(0, userId);
query.setInteger(1, day);

readInfo = (ReadInfo) query.uniqueResult();

tx.commit();
}
catch (HibernateException e)
{
log.error("catch exception:", e);

if (tx != null)
{
tx.rollback();
}

throw e;
}
return readInfo;
}


上面的代码,关键是以下几点:

1. 通过函数参数的 year, month 来确定要操作的表名,我自己写了一个 Misc.formatMoon(year, month) 来生成 "yyyyMM" 格式的字串;

2. 使用了 SQLQuery ,再通过 query.addEntity(ReadInfo.class); 建立与 ReadInfo 的映射关系;

3. query.setXxx() 与 PreparedStatement 的类似,不过索引是从 0 开始;

4. 其它的就跟一般的 Query 操作类似的了。

再看一个 insert 操作

public void insertReadInfo(ReadInfo readInfo) throws HibernateException
{
Session session = getSession();
Transaction tx = session.beginTransaction();

try
{
String sql = "insert into tblRead"
+ Misc.formatMoon(readInfo.getYear(), readInfo.getMonth())
+ " (userId, year, month, day, point) values (?, ?, ?, ?, ?)";

SQLQuery query = session.createSQLQuery(sql);

query.setLong(0, readInfo.getUserId());
query.setInteger(1, readInfo.getYear());
query.setInteger(2, readInfo.getMonth());
query.setInteger(3, readInfo.getDay());
query.setInteger(4, readInfo.getPoint());

query.executeUpdate();

tx.commit();
}
catch (HibernateException e)
{
log.error("catch exception:", e);

if (tx != null)
{
tx.rollback();
}

throw e;
}
}


同理,update, delete 等操作也是这样实现的。

hmm.. 这种处理方式的麻烦的地方是需要手工写 sql ,因此要尽量写通用的标准 sql,不然在数据库兼容方面会有问题。当然,有时是会出现无法兼容的情

况,那么可以考虑把 sql 写到配置文件中,根据不同的数据库,装载相应的配置文件咯。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值