Java for Web学习笔记(一三五)映射(11)代码触发器

说明

数据库是有触发器Trigger。但我们希望业务逻辑能从底层的具体数据存储抽象出来(有需要时可以更好存储机制),也就是要在应用中编写trigger,而不是依赖底层数据库来实现。

Entity内部触发器

我们随便挑选以前的某个entity,在里面加入触发器。

@Entity
public class Person {
    ... ...
    // 【触发器说明】
    //1、多个触发器的标记可以加到同一个方法中。
    //2、每种触发器最多只允许有一个。如果我们在superclass中定义了某个触发器,这这里也定义一个,
    //   则只有这里定义的有效。
    //3、方法可以是public,protected,package-private,private,名字无所谓。返回是void,无输入参数。
    //【注意】为避免异常,不要在这些方法中调用EntityManager的方法,或者访问其他entity。
    //       一旦出现异常,事务会回滚。

    //@PostLoad:在执行select语句后触发。如果返回多条数据,那么在ResultSet中所创建的每个entity对象均会触发。
    @PostLoad 
    void readTrigger(){
        log.debug("Person entity {} read.",this.id);
    }

    //@PrePersist:顾名思义,这是在代码中调用了EntityManager相关的persist()语句后马上执行,在
    // entity提交给EntityManager之前。注意这并不代表在数据库中马上执行,需要得到
    // transaction.commit()或者flush()时执行。在大的复杂事务中,时间差可能会挺大的。
    //【注意】如果我们在这里修改entity的属性,则最终在数据库保存的值为修订后的值
    @PrePersist 
    void beforeInsertTrigger(){
        log.debug("Person entity {} about to be inserted.",this.id);
    }

    //@PostPersist:当真实insert到数据库的时候会调用。和后面介绍的PostXXXX一样,事务在之后是可能回滚的。
    @PostPersist 
    void afterInsertTrigger() {
        log.debug("Person entity {} inserted into database.",this.id);
    }

    @PreUpdate //只要调用了setXXX(),就会触发。
    void beforeUpdateTrigger() {
        log.debug("Person entity {} just updated by call to mutator method.",this.id);
    }

    @PostUpdate 
    void afterUpdateTrigger(){
        log.debug("Person entity {} just updated in the database.",this.id);
    }

    @PreRemove 
    void beforeDeleteTrigger(){
        log.debug("Person entity {} about to be deleted.",this.id);
    }

    @PostRemove 
    void afterDeleteTrigger(){
        log.debug("Person entity {} about deleted from database.",this.id);
    }
}

Entity外部触发器:EntityListener

定义两个EntityListener,如下:

public class FirstEntityListener {
    private static final Logger log = LogManager.getLogger();
    
    //【1】EntityListener的构造函数必须是public,且无参数,本小例子无需设定

    //【2】代码编写和entity内部的触发器相似,不同时的是带有Entity的参数,可以是某个具体的Entity
    //     类,也可以是Object这种通用类。
    @PostLoad void readTrigger(Person person)
    {
        log.debug("Person entity {} read.",person.getId());
    }
 
    @PrePersist void beforeInsertTrigger(Person person)    
    {
        person.setFirstName(person.getFirstName()+ "@");
        log.debug("Person entity {} about to be inserted.",person.getId());
    }
}
public class SecondEntityListener {
    private static final Logger log = LogManager.getLogger();
    @PostLoad void readTrigger(Person person)
    {
        log.debug("Person entity {} read.",person.getId());
    }
}

将FirstEntityListener和SecondEntityListener加载Entity Person上,在上一个小例子中,我们已经在Person中加入内部的触发器。

//【1】Entity或者MappedSuperclass可以加入EntityListener,用@EntityListeners进行标记
//【2】可以加入多个EntityListner,将按顺序触发
//【3】EntityListener将优先于内部触发器执行 
//【4】如果我们不想触发superclass的EntityListener,可以加上@ExcludeSuperclassListeners,指出使
//    用哪个superclass的entityListener,如果不想触发任何superclass的entityListener,可以加上
//    @ExcludeDefaultListeners
@EntityListeners({FirstEntityListener.class,SecondEntityListener.class})
@Entity
public class Person {
    .....
}

执行结果如下:

15:20:28.682 [http-nio-8080-exec-5] [DEBUG] FirstEntityListener:13 readTrigger() - Person entity 1 read.
15:20:28.683 [http-nio-8080-exec-5] [DEBUG] SecondEntityListener:12 readTrigger() - Person entity 1 read.
15:20:28.684 [http-nio-8080-exec-5] [DEBUG] Person:83 readTrigger() - Person entity 1 read.
15:20:28.684 [http-nio-8080-exec-5] [DEBUG] FirstEntityListener:13 readTrigger() - Person entity 2 read.
15:20:28.685 [http-nio-8080-exec-5] [DEBUG] SecondEntityListener:12 readTrigger() - Person entity 2 read.
15:20:28.685 [http-nio-8080-exec-5] [DEBUG] Person:83 readTrigger() - Person entity 2 read.

附:关于entity数据变更的自动同步

@Transactional
public void secondTableTest(long id, String nickName){
	MyEmployee employee = myEmployRepository.findOne(id);
	if(employee == null)
		return;

	employee.setNickName(nickName);
//	即使我们不执行下面的save,由于已经修改了entity的内容,在transaction结束时(commit)会执行Update的SQL。
//	myEmployRepository.save(employee); 
}

相关链接:我的Professional Java for Web Applications相关文章

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值