是否存在一些更好的方式来记录更新历史记录?
Does exist some better manner to logger update history?
在我们的后端系统中,有很多情况需要更新对象,例如更新商品,更新商品价格,更新用户,更新状态,更新订单(取消,更新价格)等。现在一些对象我们有一个特殊的日志 table,例如order_update_log ,记录器更新操作。有些只记录器到文件,例如
logger.info("goods update: before: {}, after: {}", oldGoods, newGoods)
感觉处理这些琐碎的事情很烦人,有没有更好的manner/tools这样处理logger?
如果您使用 ORM 来保存数据,您可以使用 Hibernate 的 Listners/events 之类的东西来响应数据更新(并将它们记录到数据库或审计日志等)
对于休眠,这里有详细信息:https://docs.jboss.org/hibernate/orm/3.3/reference/en/html/events.html 但显然您需要调查您的持久性工具是否提供给您。
有一个非常好的东西叫做 Aspects。
您可以为您的项目编写只知道跟踪商品对象更改的方面。假设你有 Goods
class:
public class Goods {
private Integer id;
private String name;
private BigDecimal cost;
// Getters, Setters
...
}
映射到数据库table商品对应字段:
CREATE TABLE `goods` (
`id` INT NOT NULL AUTO_INCREMENT,
`name` varchar NOT NULL,
`cost` DECIMAL NOT NULL,
PRIMARY KEY (`id`)
);
假设你有 GoodsService
:
public class GoodsService {
public Goods read(Integer id) {
Goods goods = /* Read goods from database */
return goods;
}
public void write(Goods goods) {
/* Write goods to database */
}
}
和 GoodsController
使用 GoodsService
:
public class GoodsController {
private GoodsService goodsService;
public void updateGoods(Integer id, String name, BigDecimal cost) {
Goods goods = goodsService.read(id);
goods.setName(name);
goods.setCost(cost);
goodsService.write(goods);
}
}
因此,让我们为您的项目添加一些魔法来跟踪货物的变化。现在创建另一个 table,其中包含用于存储更新 goods
对象的 user
和 datetime
的附加字段:
CREATE TABLE `goods_log` (
`revision` INT NOT NULL AUTO_INCREMENT,
`id` INT NOT NULL,
`name` varchar NOT NULL,
`cost` DECIMAL NOT NULL,
`user` varchar NOT NULL,
`timestamp` DATETIME NOT NULL,
PRIMARY KEY (`revision`,`id`)
);
写方面class:
@Aspect
public class GoodsLogger {
@Before(value = "execution(* org.antonu.service.GoodsService.write(..)) && args(goods)")
public void logWrite(Goods goods) {
// Get current user and timestamp,
// Write it to goods_log table, as well as goods data
}
}
就是这样!您的业务逻辑代码没有改变,阅读起来很清楚。但是每次调用 GoodsService 的 write 方法时,您都会在 goods_log 中获得带有新商品状态的记录。
要使此代码正常工作,应使用 AJC 编译器对其进行编译,还应包括 aspectjrt 库。它可以通过 maven 轻松完成:
<properties>
<aspectj.version>1.8.7</aspectj.version>
</properties>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
现代 IDE Intellij Idea 应该自动使用 AJC
编译器和上面的 maven 配置。如果没有,您必须通过 File - Settings - 'Build, Execution, Deployment' - Compiler - Java Compiler - Use compiler: Ajc.
AJC 编译器路径配置编译器:<path_to>/aspectjtools-1.8.7.jar
在我们的后端系统中,有很多情况需要更新对象,例如更新商品,更新商品价格,更新用户,更新状态,更新订单(取消,更新价格)等。现在一些对象我们有一个特殊的日志 table,例如order_update_log ,记录器更新操作。有些只记录器到文件,例如
logger.info("goods update: before: {}, after: {}", oldGoods, newGoods)
感觉处理这些琐碎的事情很烦人,有没有更好的manner/tools这样处理logger?
如果您使用 ORM 来保存数据,您可以使用 Hibernate 的 Listners/events 之类的东西来响应数据更新(并将它们记录到数据库或审计日志等) 对于休眠,这里有详细信息:https://docs.jboss.org/hibernate/orm/3.3/reference/en/html/events.html 但显然您需要调查您的持久性工具是否提供给您。
有一个非常好的东西叫做 Aspects。
您可以为您的项目编写只知道跟踪商品对象更改的方面。假设你有 Goods
class:
public class Goods {
private Integer id;
private String name;
private BigDecimal cost;
// Getters, Setters
...
}
映射到数据库table商品对应字段:
CREATE TABLE `goods` (
`id` INT NOT NULL AUTO_INCREMENT,
`name` varchar NOT NULL,
`cost` DECIMAL NOT NULL,
PRIMARY KEY (`id`)
);
假设你有 GoodsService
:
public class GoodsService {
public Goods read(Integer id) {
Goods goods = /* Read goods from database */
return goods;
}
public void write(Goods goods) {
/* Write goods to database */
}
}
和 GoodsController
使用 GoodsService
:
public class GoodsController {
private GoodsService goodsService;
public void updateGoods(Integer id, String name, BigDecimal cost) {
Goods goods = goodsService.read(id);
goods.setName(name);
goods.setCost(cost);
goodsService.write(goods);
}
}
因此,让我们为您的项目添加一些魔法来跟踪货物的变化。现在创建另一个 table,其中包含用于存储更新 goods
对象的 user
和 datetime
的附加字段:
CREATE TABLE `goods_log` (
`revision` INT NOT NULL AUTO_INCREMENT,
`id` INT NOT NULL,
`name` varchar NOT NULL,
`cost` DECIMAL NOT NULL,
`user` varchar NOT NULL,
`timestamp` DATETIME NOT NULL,
PRIMARY KEY (`revision`,`id`)
);
写方面class:
@Aspect
public class GoodsLogger {
@Before(value = "execution(* org.antonu.service.GoodsService.write(..)) && args(goods)")
public void logWrite(Goods goods) {
// Get current user and timestamp,
// Write it to goods_log table, as well as goods data
}
}
就是这样!您的业务逻辑代码没有改变,阅读起来很清楚。但是每次调用 GoodsService 的 write 方法时,您都会在 goods_log 中获得带有新商品状态的记录。
要使此代码正常工作,应使用 AJC 编译器对其进行编译,还应包括 aspectjrt 库。它可以通过 maven 轻松完成:
<properties>
<aspectj.version>1.8.7</aspectj.version>
</properties>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
现代 IDE Intellij Idea 应该自动使用 AJC
编译器和上面的 maven 配置。如果没有,您必须通过 File - Settings - 'Build, Execution, Deployment' - Compiler - Java Compiler - Use compiler: Ajc.
AJC 编译器路径配置编译器:<path_to>/aspectjtools-1.8.7.jar