从单个整体式 springboot 应用程序对两个独立数据库中的表执行写入
Performing writes to tables in two separate databases from a single monolithic springboot application
我在工作中有一个单一的服务。有一个 mysql 数据库说它连接到 X。 X 有很多 table。 X 现在已经成为扩展的瓶颈,因此我正在努力从 X 中删除非关键的 tables 到一个单独的实例,比如 Y。目前我的目标是将一些审计 tables 从中移出X 到 Y。
行动计划如下:
1) DBA 团队正在创建一个新的数据库实例,其目标 tables of X。不确定具体细节。
2)在应用程序方面,我正在考虑创建多个将连接到新实例 Y 的休眠会话工厂。然后我计划使用功能门标志来修改目标应用程序的 read/write 行为 table秒。
2.1) 写入功能标志的值为 0(写入旧数据库)、1(写入旧数据库和新数据库)、2(写入新数据库)。
2.2) 读取特征标志的值为 0(从旧数据库读取)、1(从新数据库读取)。
部署当天,
1) 我们计划停机
2) DBA 团队将为新实例做好准备
3) 我将应用程序的写入功能标志设置为模式 1,读取功能标志仍为 0。如果设置运行正常可能几周,然后将读取标志迁移到 1 并将写入标志迁移到 2。
请大家帮我解决计划中的缺陷。
单体服务是遗留服务,是 springboot 1.4.0 with spring orm。 Mysql版本是5.7
谈到我的主要问题,即启用一个设置,比如在两个单独的数据库中写入 tables。我已经按照 link Hibernate configuring multiple datasources and multiple session factories 应用程序连接到多个数据库。我复制了目标 tables 的实体和 dao。在服务方法中,我添加了根据功能标志编写的代码。但是,当我使用写入模式 1 测试代码时,数据会持久保存到 X 但不会持久保存在 Y 中。我已经使用 format_sql 和 show_sql true 进行了很多调试,但我无法找出原因。
通过 sequel pro 访问数据库 X 和 Y,我已经验证数据在 X 中的目标 table 中持久化,但在 Y 中的目标 table 中不持久化。虽然当我通过查询在 Y 中的目标 table 中插入一行时,作为自动生成字段的主 ID 字段的值增加了。
@Entity
@Data
@Table(name = "time_audit")
public class TimeAudit {
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name="id") private long id;
@Column(name="order_id") private String orderId;
@Column(name = "status") private String status;
@Column(name = "duration") private Double duration;
@Column(name = "calculated_for") private String calculatedFor;
}
@Entity
@Data
@Table(name = "time_audit_v2")
public class TimeAuditV2 {
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "id")
private long id;
@Column(name = "order_id")
private String orderId;
@Column(name = "status")
private String status;
@Column(name = "duration")
private Double duration;
@Column(name = "calculated_for")
private String calculatedFor;
}
@Repository
public class TimeAuditDaoImpl implements TimeAuditDao {
@Autowired
@Qualifier("sessionFactory") private SessionFactory sessionFactory;
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void saveTimeAudit(Double time, String orderId, String status, String calculatedFor){
Session session = sessionFactory.getCurrentSession();
TimeAudit timeAudit = new TimeAudit();
timeAudit.setDuration(time);
timeAudit.setOrderId(orderId);
timeAudit.setStatus(status);
timeAudit.setCalculatedFor(calculatedFor);
session.save(timeAudit);
}
}
@Repository
public class TimeAuditDaoImplV2 implements TimeAuditDaoV2 {
@Autowired
@Qualifier("taskSeqAuditSessionFactory")
private SessionFactory taskSeqAuditSessionFactory;
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void saveTimeAudit(Double time, String orderId, String status, String calculatedFor) {
Session session = taskSeqAuditSessionFactory.getCurrentSession();
TimeAuditV2 timeAudit = new TimeAuditV2();
timeAudit.setDuration(time);
timeAudit.setOrderId(orderId);
timeAudit.setStatus(status);
timeAudit.setCalculatedFor(calculatedFor);
session.save(timeAudit);
}
}
@Service
public class TimeAuditServiceImpl implements TimeAuditService {
@Autowired
private DeliveryConfigDao deliveryConfigDao;
@Autowired
private TimeAuditDao timeAuditDao;
@Autowired
private TimeAuditDaoV2 timeAuditDaoV2;
@Transactional(propagation = Propagation.REQUIRED)
@Override
public void saveTimeAudit(Double time, String orderId, String status, String calculatedFor) {
String taskSeqAuditSwitch = deliveryConfigDao.getConfig(GenericStringConstants.TASK_SEQ_AUDIT_WRITE_FEATURE_KEY, GenericStringConstants.TASK_SEQ_AUDIT_WRITE_DELIVERY_DB);
if (taskSeqAuditSwitch.equalsIgnoreCase(GenericStringConstants.TASK_SEQ_AUDIT_WRITE_DELIVERY_DB)) {
timeAuditDao.saveTimeAudit(time, orderId, status, calculatedFor);
} else if (taskSeqAuditSwitch.equalsIgnoreCase(GenericStringConstants.TASK_SEQ_AUDIT_WRITE_BOTH_DB)) {
timeAuditDao.saveTimeAudit(time, orderId, status, calculatedFor);
timeAuditDaoV2.saveTimeAudit(time, orderId, status, calculatedFor);
} else if (taskSeqAuditSwitch.equalsIgnoreCase(GenericStringConstants.TASK_SEQ_AUDIT_WRITE_TASK_SEQ_DB)) {
timeAuditDaoV2.saveTimeAudit(time, orderId, status, calculatedFor);
}
}
}
[database.xml]
<bean id="slaveSessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">com.swiggy.delivery.deliveryboy.model.dao.CustomMySql5Dialect</prop>
<prop key="hibernate.show_sql">${hibernate.slave.showSql}</prop>
<prop key="hibernate.format_sql">${hibernate.slave.formatSql}</prop>
<prop key="hibernate.connection.url">${hibernate.slave.connection.url}</prop>
<prop key="hibernate.connection.driver_class">com.mysql.jdbc.ReplicationDriver</prop>
<prop key="hibernate.connection.username">${hibernate.slave.connection.username}</prop>
<prop key="hibernate.connection.password">${hibernate.slave.connection.password}</prop>
<prop key="hibernate.c3p0.min_size">${hibernate.slave.c3p0.min_size}</prop>
<prop key="hibernate.c3p0.max_size">${hibernate.slave.c3p0.max_size}</prop>
<prop key="hibernate.c3p0.timeout">300</prop>
<prop key="hibernate.c3p0.max_statements">0</prop>
<prop key="hibernate.c3p0.idle_test_period">3000</prop>
<prop key="hibernate.c3p0.max_idle_time_excess_connections">60</prop>
</props>
</property>
<property name="packagesToScan"
value="com.swiggy.delivery.data.sql.entities, com.swiggy.delivery.referral.data.sql.entities, com.swiggy.delivery.sno.data.sql.entities, com.swiggy.delivery.apartmentSecurityPartners.data.sql.entities, com.swiggy.delivery.callStatus.data.sql.entities,
com.swiggy.delivery.loyaltyProgram.entities,com.swiggy.delivery.daily.entities,com.swiggy.delivery.service_line.entities,com.swiggy.delivery.hub.entities, com.swiggy.delivery.userCityMapping.entities,com.swiggy.delivery.userZoneMapping.entities,com.swiggy.delivery.userHubMapping.entities,com.swiggy.delivery.nudge.de.sql.entities,com.swiggy.delivery.bank.account.validation.entities"/>
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" primary="true">
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">${hibernate.showSql}</prop>
<prop key="hibernate.format_sql">${hibernate.formatSql}</prop>
<prop key="hibernate.connection.url">${hibernate.connection.url}</prop>
<prop key="hibernate.connection.driver_class">com.mysql.jdbc.Driver</prop>
<prop key="hibernate.connection.username">${hibernate.connection.username}</prop>
<prop key="hibernate.connection.password">${hibernate.connection.password}</prop>
<prop key="hibernate.c3p0.min_size">${hibernate.c3p0.min_size}</prop>
<prop key="hibernate.c3p0.max_size">${hibernate.c3p0.max_size}</prop>
<prop key="hibernate.c3p0.timeout">300</prop>
<prop key="hibernate.c3p0.max_statements">0</prop>
<prop key="hibernate.c3p0.idle_test_period">3000</prop>
</props>
</property>
</bean>
<bean id="taskSeqAuditSessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" >
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">${hibernate.taskSeqAudit.showSql}</prop>
<prop key="hibernate.format_sql">${hibernate.taskSeqAudit.formatSql}</prop>
<prop key="hibernate.connection.url">${hibernate.taskSeqAudit.connection.url}</prop>
<prop key="hibernate.connection.driver_class">com.mysql.jdbc.Driver</prop>
<prop key="hibernate.connection.username">${hibernate.taskSeqAudit.connection.username}</prop>
<prop key="hibernate.connection.password">${hibernate.taskSeqAudit.connection.password}</prop>
<prop key="hibernate.c3p0.min_size">${hibernate.taskSeqAudit.c3p0.min_size}</prop>
<prop key="hibernate.c3p0.max_size">${hibernate.taskSeqAudit.c3p0.max_size}</prop>
<prop key="hibernate.c3p0.timeout">300</prop>
<prop key="hibernate.c3p0.max_statements">0</prop>
<prop key="hibernate.c3p0.idle_test_period">3000</prop>
</props>
</property>
<property name="packagesToScan" value="com.swiggy.delivery.data.sql.entities" />
</bean>
<bean id="slaveTaskSeqAuditSessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" >
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">${hibernate.slave.taskSeqAudit.showSql}</prop>
<prop key="hibernate.format_sql">${hibernate.slave.taskSeqAudit.formatSql}</prop>
<prop key="hibernate.connection.url">${hibernate.slave.taskSeqAudit.connection.url}</prop>
<prop key="hibernate.connection.driver_class">com.mysql.jdbc.Driver</prop>
<prop key="hibernate.connection.username">${hibernate.slave.taskSeqAudit.connection.username}</prop>
<prop key="hibernate.connection.password">${hibernate.slave.taskSeqAudit.connection.password}</prop>
<prop key="hibernate.c3p0.min_size">${hibernate.slave.taskSeqAudit.c3p0.min_size}</prop>
<prop key="hibernate.c3p0.max_size">${hibernate.slave.taskSeqAudit.c3p0.max_size}</prop>
<prop key="hibernate.c3p0.timeout">300</prop>
<prop key="hibernate.c3p0.max_statements">0</prop>
<prop key="hibernate.c3p0.idle_test_period">3000</prop>
</props>
</property>
<property name="packagesToScan" value="com.swiggy.delivery.data.sql.entities" />
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager" primary="true">
<property name="sessionFactory" ref="sessionFactory" />
<property name="defaultTimeout" value="10" />
</bean>
<bean id="slaveTransactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="slaveSessionFactory" />
<property name="defaultTimeout" value="10" />
</bean>
<bean id="taskSeqAuditTransactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="taskSeqAuditSessionFactory" />
<property name="defaultTimeout" value="10" />
</bean>
<bean id="slaveTaskSeqAuditTransactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="slaveTaskSeqAuditSessionFactory" />
<property name="defaultTimeout" value="10" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<tx:annotation-driven transaction-manager="slaveTransactionManager"/>
<tx:annotation-driven transaction-manager="taskSeqAuditTransactionManager"/>
<tx:annotation-driven transaction-manager="slaveTaskSeqAuditTransactionManager"/>
假设您想要将对象写入(休眠)到两个不同数据库中的表中,也许与此相关的 springboot 1.4 上的旧教程可能有所帮助:
http://roufid.com/spring-boot-multiple-databases-configuration/
您将必须创建两个数据源,实体管理器和事务管理器。
干杯
PS:我假设是因为您的问题中没有具体指示,并且在您描述的场景中没有更多指示具体代码问题,任何日志和测试结果都支持, and/or 错误信息。请记住,问题越具体,答案就越不模糊。
已确定问题。 saveTimeAudit TimeAuditDaoImplV2 中的方法存在错误的 Transactional 注释问题。虽然我正在使用连接到 DB Y 的 sessionFactory,但默认情况下 Transactional 注释使用不属于 DB Y 会话的主事务管理器。
修改注解为
@Transactional(value = "taskSeqAuditTransactionManager")
此修改确保了 DB Y 的事务管理器与 DB Y 的 sessionFactory 一起使用,现在数据在两个 DB(即 X 和 Y)中持久存在。
还从 TimeAuditServiceImpl class.
中的 saveTimeAudit 方法中删除了 Transactional 注释
我在工作中有一个单一的服务。有一个 mysql 数据库说它连接到 X。 X 有很多 table。 X 现在已经成为扩展的瓶颈,因此我正在努力从 X 中删除非关键的 tables 到一个单独的实例,比如 Y。目前我的目标是将一些审计 tables 从中移出X 到 Y。 行动计划如下: 1) DBA 团队正在创建一个新的数据库实例,其目标 tables of X。不确定具体细节。 2)在应用程序方面,我正在考虑创建多个将连接到新实例 Y 的休眠会话工厂。然后我计划使用功能门标志来修改目标应用程序的 read/write 行为 table秒。 2.1) 写入功能标志的值为 0(写入旧数据库)、1(写入旧数据库和新数据库)、2(写入新数据库)。 2.2) 读取特征标志的值为 0(从旧数据库读取)、1(从新数据库读取)。
部署当天, 1) 我们计划停机 2) DBA 团队将为新实例做好准备 3) 我将应用程序的写入功能标志设置为模式 1,读取功能标志仍为 0。如果设置运行正常可能几周,然后将读取标志迁移到 1 并将写入标志迁移到 2。
请大家帮我解决计划中的缺陷。
单体服务是遗留服务,是 springboot 1.4.0 with spring orm。 Mysql版本是5.7 谈到我的主要问题,即启用一个设置,比如在两个单独的数据库中写入 tables。我已经按照 link Hibernate configuring multiple datasources and multiple session factories 应用程序连接到多个数据库。我复制了目标 tables 的实体和 dao。在服务方法中,我添加了根据功能标志编写的代码。但是,当我使用写入模式 1 测试代码时,数据会持久保存到 X 但不会持久保存在 Y 中。我已经使用 format_sql 和 show_sql true 进行了很多调试,但我无法找出原因。
通过 sequel pro 访问数据库 X 和 Y,我已经验证数据在 X 中的目标 table 中持久化,但在 Y 中的目标 table 中不持久化。虽然当我通过查询在 Y 中的目标 table 中插入一行时,作为自动生成字段的主 ID 字段的值增加了。
@Entity
@Data
@Table(name = "time_audit")
public class TimeAudit {
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name="id") private long id;
@Column(name="order_id") private String orderId;
@Column(name = "status") private String status;
@Column(name = "duration") private Double duration;
@Column(name = "calculated_for") private String calculatedFor;
}
@Entity
@Data
@Table(name = "time_audit_v2")
public class TimeAuditV2 {
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "id")
private long id;
@Column(name = "order_id")
private String orderId;
@Column(name = "status")
private String status;
@Column(name = "duration")
private Double duration;
@Column(name = "calculated_for")
private String calculatedFor;
}
@Repository
public class TimeAuditDaoImpl implements TimeAuditDao {
@Autowired
@Qualifier("sessionFactory") private SessionFactory sessionFactory;
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void saveTimeAudit(Double time, String orderId, String status, String calculatedFor){
Session session = sessionFactory.getCurrentSession();
TimeAudit timeAudit = new TimeAudit();
timeAudit.setDuration(time);
timeAudit.setOrderId(orderId);
timeAudit.setStatus(status);
timeAudit.setCalculatedFor(calculatedFor);
session.save(timeAudit);
}
}
@Repository
public class TimeAuditDaoImplV2 implements TimeAuditDaoV2 {
@Autowired
@Qualifier("taskSeqAuditSessionFactory")
private SessionFactory taskSeqAuditSessionFactory;
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void saveTimeAudit(Double time, String orderId, String status, String calculatedFor) {
Session session = taskSeqAuditSessionFactory.getCurrentSession();
TimeAuditV2 timeAudit = new TimeAuditV2();
timeAudit.setDuration(time);
timeAudit.setOrderId(orderId);
timeAudit.setStatus(status);
timeAudit.setCalculatedFor(calculatedFor);
session.save(timeAudit);
}
}
@Service
public class TimeAuditServiceImpl implements TimeAuditService {
@Autowired
private DeliveryConfigDao deliveryConfigDao;
@Autowired
private TimeAuditDao timeAuditDao;
@Autowired
private TimeAuditDaoV2 timeAuditDaoV2;
@Transactional(propagation = Propagation.REQUIRED)
@Override
public void saveTimeAudit(Double time, String orderId, String status, String calculatedFor) {
String taskSeqAuditSwitch = deliveryConfigDao.getConfig(GenericStringConstants.TASK_SEQ_AUDIT_WRITE_FEATURE_KEY, GenericStringConstants.TASK_SEQ_AUDIT_WRITE_DELIVERY_DB);
if (taskSeqAuditSwitch.equalsIgnoreCase(GenericStringConstants.TASK_SEQ_AUDIT_WRITE_DELIVERY_DB)) {
timeAuditDao.saveTimeAudit(time, orderId, status, calculatedFor);
} else if (taskSeqAuditSwitch.equalsIgnoreCase(GenericStringConstants.TASK_SEQ_AUDIT_WRITE_BOTH_DB)) {
timeAuditDao.saveTimeAudit(time, orderId, status, calculatedFor);
timeAuditDaoV2.saveTimeAudit(time, orderId, status, calculatedFor);
} else if (taskSeqAuditSwitch.equalsIgnoreCase(GenericStringConstants.TASK_SEQ_AUDIT_WRITE_TASK_SEQ_DB)) {
timeAuditDaoV2.saveTimeAudit(time, orderId, status, calculatedFor);
}
}
}
[database.xml]
<bean id="slaveSessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">com.swiggy.delivery.deliveryboy.model.dao.CustomMySql5Dialect</prop>
<prop key="hibernate.show_sql">${hibernate.slave.showSql}</prop>
<prop key="hibernate.format_sql">${hibernate.slave.formatSql}</prop>
<prop key="hibernate.connection.url">${hibernate.slave.connection.url}</prop>
<prop key="hibernate.connection.driver_class">com.mysql.jdbc.ReplicationDriver</prop>
<prop key="hibernate.connection.username">${hibernate.slave.connection.username}</prop>
<prop key="hibernate.connection.password">${hibernate.slave.connection.password}</prop>
<prop key="hibernate.c3p0.min_size">${hibernate.slave.c3p0.min_size}</prop>
<prop key="hibernate.c3p0.max_size">${hibernate.slave.c3p0.max_size}</prop>
<prop key="hibernate.c3p0.timeout">300</prop>
<prop key="hibernate.c3p0.max_statements">0</prop>
<prop key="hibernate.c3p0.idle_test_period">3000</prop>
<prop key="hibernate.c3p0.max_idle_time_excess_connections">60</prop>
</props>
</property>
<property name="packagesToScan"
value="com.swiggy.delivery.data.sql.entities, com.swiggy.delivery.referral.data.sql.entities, com.swiggy.delivery.sno.data.sql.entities, com.swiggy.delivery.apartmentSecurityPartners.data.sql.entities, com.swiggy.delivery.callStatus.data.sql.entities,
com.swiggy.delivery.loyaltyProgram.entities,com.swiggy.delivery.daily.entities,com.swiggy.delivery.service_line.entities,com.swiggy.delivery.hub.entities, com.swiggy.delivery.userCityMapping.entities,com.swiggy.delivery.userZoneMapping.entities,com.swiggy.delivery.userHubMapping.entities,com.swiggy.delivery.nudge.de.sql.entities,com.swiggy.delivery.bank.account.validation.entities"/>
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" primary="true">
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">${hibernate.showSql}</prop>
<prop key="hibernate.format_sql">${hibernate.formatSql}</prop>
<prop key="hibernate.connection.url">${hibernate.connection.url}</prop>
<prop key="hibernate.connection.driver_class">com.mysql.jdbc.Driver</prop>
<prop key="hibernate.connection.username">${hibernate.connection.username}</prop>
<prop key="hibernate.connection.password">${hibernate.connection.password}</prop>
<prop key="hibernate.c3p0.min_size">${hibernate.c3p0.min_size}</prop>
<prop key="hibernate.c3p0.max_size">${hibernate.c3p0.max_size}</prop>
<prop key="hibernate.c3p0.timeout">300</prop>
<prop key="hibernate.c3p0.max_statements">0</prop>
<prop key="hibernate.c3p0.idle_test_period">3000</prop>
</props>
</property>
</bean>
<bean id="taskSeqAuditSessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" >
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">${hibernate.taskSeqAudit.showSql}</prop>
<prop key="hibernate.format_sql">${hibernate.taskSeqAudit.formatSql}</prop>
<prop key="hibernate.connection.url">${hibernate.taskSeqAudit.connection.url}</prop>
<prop key="hibernate.connection.driver_class">com.mysql.jdbc.Driver</prop>
<prop key="hibernate.connection.username">${hibernate.taskSeqAudit.connection.username}</prop>
<prop key="hibernate.connection.password">${hibernate.taskSeqAudit.connection.password}</prop>
<prop key="hibernate.c3p0.min_size">${hibernate.taskSeqAudit.c3p0.min_size}</prop>
<prop key="hibernate.c3p0.max_size">${hibernate.taskSeqAudit.c3p0.max_size}</prop>
<prop key="hibernate.c3p0.timeout">300</prop>
<prop key="hibernate.c3p0.max_statements">0</prop>
<prop key="hibernate.c3p0.idle_test_period">3000</prop>
</props>
</property>
<property name="packagesToScan" value="com.swiggy.delivery.data.sql.entities" />
</bean>
<bean id="slaveTaskSeqAuditSessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" >
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">${hibernate.slave.taskSeqAudit.showSql}</prop>
<prop key="hibernate.format_sql">${hibernate.slave.taskSeqAudit.formatSql}</prop>
<prop key="hibernate.connection.url">${hibernate.slave.taskSeqAudit.connection.url}</prop>
<prop key="hibernate.connection.driver_class">com.mysql.jdbc.Driver</prop>
<prop key="hibernate.connection.username">${hibernate.slave.taskSeqAudit.connection.username}</prop>
<prop key="hibernate.connection.password">${hibernate.slave.taskSeqAudit.connection.password}</prop>
<prop key="hibernate.c3p0.min_size">${hibernate.slave.taskSeqAudit.c3p0.min_size}</prop>
<prop key="hibernate.c3p0.max_size">${hibernate.slave.taskSeqAudit.c3p0.max_size}</prop>
<prop key="hibernate.c3p0.timeout">300</prop>
<prop key="hibernate.c3p0.max_statements">0</prop>
<prop key="hibernate.c3p0.idle_test_period">3000</prop>
</props>
</property>
<property name="packagesToScan" value="com.swiggy.delivery.data.sql.entities" />
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager" primary="true">
<property name="sessionFactory" ref="sessionFactory" />
<property name="defaultTimeout" value="10" />
</bean>
<bean id="slaveTransactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="slaveSessionFactory" />
<property name="defaultTimeout" value="10" />
</bean>
<bean id="taskSeqAuditTransactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="taskSeqAuditSessionFactory" />
<property name="defaultTimeout" value="10" />
</bean>
<bean id="slaveTaskSeqAuditTransactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="slaveTaskSeqAuditSessionFactory" />
<property name="defaultTimeout" value="10" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<tx:annotation-driven transaction-manager="slaveTransactionManager"/>
<tx:annotation-driven transaction-manager="taskSeqAuditTransactionManager"/>
<tx:annotation-driven transaction-manager="slaveTaskSeqAuditTransactionManager"/>
假设您想要将对象写入(休眠)到两个不同数据库中的表中,也许与此相关的 springboot 1.4 上的旧教程可能有所帮助:
http://roufid.com/spring-boot-multiple-databases-configuration/
您将必须创建两个数据源,实体管理器和事务管理器。
干杯
PS:我假设是因为您的问题中没有具体指示,并且在您描述的场景中没有更多指示具体代码问题,任何日志和测试结果都支持, and/or 错误信息。请记住,问题越具体,答案就越不模糊。
已确定问题。 saveTimeAudit TimeAuditDaoImplV2 中的方法存在错误的 Transactional 注释问题。虽然我正在使用连接到 DB Y 的 sessionFactory,但默认情况下 Transactional 注释使用不属于 DB Y 会话的主事务管理器。
修改注解为
@Transactional(value = "taskSeqAuditTransactionManager")
此修改确保了 DB Y 的事务管理器与 DB Y 的 sessionFactory 一起使用,现在数据在两个 DB(即 X 和 Y)中持久存在。
还从 TimeAuditServiceImpl class.