Jpa 如何使用@EntityListeners 实现实体对象的自动赋值

时间:2022-11-14 17:33:48

1、简介

1.1 @entitylisteners

官方解释:可以使用生命周期注解指定实体中的方法,这些方法在指定的生命周期事件发生时执行相应的业务逻辑。

简单来说,就是监听实体对象的增删改查操作,并对实体对象进行相应的处理。

1.2 生命周期对应注解

jpa一共提供了7种注解,分别是:

@postload :实体对象查询之后

@prepersist : 实体对象保存之前

@postpersist :实体对象保存之后

@preupdate :实体对象修改之前

@postupdate :实体对象修改之后

@preremove : 实体对象删除之前

@postremove :实体对象删除之后

通常情况下,数据表中都会记录创建人、创建时间、修改人、修改时间等通用属性。如果每个实体对象都要对这些通用属性手动赋值,就会过于繁琐。

现在,使用这些生命周期注解,就可以实现对通用属性的自动赋值,或者记录相应操作日志。

2、环境准备

数据库:mysql

项目搭建:演示项目通过spring boot 2.2.6构建,引入spring-boot-starter-data-jpa

2.1 数据表

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
-- 用户表
create table `acc_user` (
  `id` bigint(20) not null auto_increment,
  `username` varchar(40) not null default '' comment '用户名',
  `password` varchar(40) not null default '' comment '密码',
  `create_by` varchar(80) default null,
  `create_time` datetime default current_timestamp,
  `update_by` varchar(80) default null,
  `update_time` datetime default current_timestamp on update current_timestamp,
  primary key (`id`)
) engine=innodb default charset=utf8mb4;
-- 日志表
create table `modify_log` (
  `id` bigint(20) not null auto_increment,
  `action` varchar(20) not null default '' comment '操作',
  `entity_name` varchar(40) not null default '' comment '实体类名',
  `entity_key` varchar(20) default null comment '主键值',
  `entity_value` varchar(400) default null comment '实体值',
  `create_by` varchar(80) default null,
  `create_time` datetime default current_timestamp,
  primary key (`id`)
) engine=innodb default charset=utf8mb4;

2.2 实体类

?
1
2
3
4
5
6
7
8
9
10
11
12
@mappedsuperclass
@getter @setter
@mappedsuperclass
// 指定对应监听类
@entitylisteners(createlistener.class)
public abstract class idmapped {
    @id
    @generatedvalue(strategy = generationtype.identity)
    private long id;
    private string createby;
    private date createtime;
}
?
1
2
3
4
5
6
7
8
@getter @setter
@mappedsuperclass
// 指定对应监听类
@entitylisteners(editlistener.class)
public abstract class editmapped extends idmapped{
    private string updateby;
    private date updatetime;
}

用户类

?
1
2
3
4
5
6
7
@entity
@table(name = "acc_user")
@getter @setter
public class userentity extends editmapped {
    private string username;
    private string password;
}

日志类

?
1
2
3
4
5
6
7
8
9
@entity
@table(name = "modify_log")
@getter @setter
public class modifylogentity extends idmapped{
    private string  action;
    private string  entityname;
    private string  entitykey;
    private string  entityvalue;
}

2.3 监听类

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class createlistener extends basiclistener {
    // 保存之前,为创建时间和创建人赋值
    @prepersist
    public void prepersist(idmapped idmapped) {
        if (objects.isnull(idmapped.getcreatetime())) {
            idmapped.setcreatetime(new date());
        }
        if (stringutils.isblank(idmapped.getcreateby())) {
            // 根据鉴权系统实现获取当前操作用户,此处只做模拟
            idmapped.setcreateby("test_create");
        }
    }
    // 保存之后,记录变更日志
    @postpersist
    public void postpersist(idmapped idmapped) throws jsonprocessingexception {
        recordlog(action_insert, idmapped);
    }
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class editlistener extends basiclistener {
    // 修改之前,为修改人和修改时间赋值
    @preupdate
    public void preupdate(editmapped editmapped) {
        if (objects.isnull(editmapped.getupdatetime())) {
            editmapped.setcreatetime(new date());
        }
        if (stringutils.isblank(editmapped.getupdateby())) {
            // 根据鉴权系统实现获取当前操作用户,此处只做模拟
            editmapped.setupdateby("test_update");
        }
    }
    // 修改之后,记录变更日志
    @postupdate
    public void postupdate(editmapped editmapped) throws jsonprocessingexception {
        recordlog(action_update, editmapped);
    }
    // 删除之前,记录变更日志
    @preremove
    public void preremove(editmapped editmapped) throws jsonprocessingexception {
        recordlog(action_delete, editmapped);
    }
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class basiclistener implements applicationcontextaware {
    private applicationcontext applicationcontext;
    protected static final string action_insert = "insert";
    protected static final string action_update = "update";
    protected static final string action_delete = "delete";
    // 记录变更日志
    protected void recordlog(string action, idmapped object) throws jsonprocessingexception {
        // 日志对象不需要再记录变更日志
        if (object instanceof modifylogentity) {
            return;
        }
        modifylogentity modifylogentity = new modifylogentity();
        modifylogentity.setaction(action);
        modifylogentity.setentitykey(string.valueof(object.getid()));
        modifylogentity.setentityname(object.getclass().getsimplename());
        // 对象转json字符串存储
        modifylogentity.setentityvalue(new objectmapper().writevalueasstring(object));
        optional.ofnullable(applicationcontext.getbean(modifylogdao.class))
                .ifpresent(modifylogdao -> modifylogdao.save(modifylogentity));
    }
    @override
    public void setapplicationcontext(applicationcontext applicationcontext) throws beansexception {
        this.applicationcontext = applicationcontext;
    }
}

3、测试

3.1 dao

?
1
2
3
@repository
public interface userdao extends jparepository<userentity, long> {
}
?
1
2
3
@repository
public interface modifylogdao extends jparepository<modifylogentity, long> {
}

3.2 service

模拟用户的创建、修改和删除操作

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@service
public class userserviceimpl implements userservice {
    @autowired
    private userdao userdao;
    @override
    @transactional
    public void add(string username, string password) {
        userentity userentity = new userentity();
        userentity.setusername(username);
        userentity.setpassword(password);
        userdao.save(userentity);
    }
    @override
    @transactional
    public void update(long id, string password) {
        userentity userentity = userdao.findbyid(id).orelsethrow(() -> new runtimeexception("用户不存在"));
        userentity.setpassword(password);
        userdao.save(userentity);
    }
    @override
    @transactional
    public void delete(long id) {
        userentity userentity = userdao.findbyid(id).orelsethrow(() -> new runtimeexception("用户不存在"));
        userdao.delete(userentity);
    }
}

3.3 测试

3.3.1 创建用户

?
1
2
3
4
5
6
7
8
9
@springboottest
public class schoolapplicationtests {
    @autowired
    private userservice userservice;
    @test
    public void testadd() {
        userservice.add("test1", "123456");
    }   
}

测试结果

Jpa 如何使用@EntityListeners 实现实体对象的自动赋值Jpa 如何使用@EntityListeners 实现实体对象的自动赋值

3.3.2 修改用户

?
1
2
3
4
@test
public void testupdate() {
    userservice.update(1l, "654321");
}

测试结果

Jpa 如何使用@EntityListeners 实现实体对象的自动赋值

Jpa 如何使用@EntityListeners 实现实体对象的自动赋值

3.3.3 删除用户

?
1
2
3
4
@test
public void testremove() {
    userservice.delete(1l);
}

测试结果

Jpa 如何使用@EntityListeners 实现实体对象的自动赋值

以上为个人经验,希望能给大家一个参考,也希望大家多多支持服务器之家。

原文链接:https://blog.csdn.net/loushangdeanshi/article/details/106042385