进一步理解get和set

做CRUD的功能时,我们常常会定义一个和表对应的实体类信息,然后这个实体类信息的属性和表中的字段一一对应,然后加上每个属性的get和set方法;更规范的做法是,在此基础上再加一个DTO类,它与实体类

长得几乎一样,但是这个类不直接和表关联。

之前一直不明白为何要再定义一个dto类,也觉得get和set方法不外乎是:

public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		
		this.email = email;
	}

 这种“千篇一律”的写法。。直到最近做了对字段加解密的活,才被虐得很惨。。

下面就以对email字段来加解密,说一说我的收获。

假设有一个和表对应的实体类Info(Hibernate):

@SuppressWarnings("serial")
@Table(name = "INFO")
@Entity
public class Info extends BasicEntity {
	@Column(name = "EMAIL")
	private String email;
	
	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		
		this.email = email;
	}
}

 还有一个对应的DTO:

public class InfoDTO  {
	
	private String email;
	
	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		
		this.email = email;
	}
}

 现在如果要对email字段加解密,就是在数据库里看到的是密文,在前端UI看到的是明文。此时就跟get和set有关了。。

我们在此不讨论如何加解密。一般而言,Entity的set方法用于保存入库,get方法用于从库里取数据,你会很正常的想到这样:

@SuppressWarnings("serial")
@Table(name = "INFO")
@Entity
public class Info extends BasicEntity {
	@Column(name = "EMAIL")
	private String email;
	
	public String getEmail() {
		email = ....(emial);//解密的伪代码
		return email;
	}

	public void setEmail(String email) {
		email = ....(emial);//加密的伪代码
		this.email = email;
	}
}

 set方法没有问题,但是get方法就是一个“陷阱”!在首次解密数据库里的密文email时,确实能在前端正常显示明文,但是同时数据库里的email字段也会变成明文!我们在第二次以后再去访问时,因为已经是

明文,再解密的话就会报错!

所以get方法也可能改变数据库里的值,因为一旦你在get方法里对该字段做了逻辑处理后,email是全局变量,会直接影响数据库里面的值!一般我们只认为set会改变库里的值,而get不会。但是要看get方法里

有没有对变量做逻辑处理,这就颠覆了"固化"的思维。

此时DTO类就派上用场啦!可以这样改造,保持Entity实体类的get方法不变,DTO类的get方法再做解密!如:

@SuppressWarnings("serial")
@Table(name = "INFO")
@Entity
public class Info extends BasicEntity {
	@Column(name = "EMAIL")
	private String email;
	
	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		email = ....(emial);//加密的伪代码
		this.email = email;
	}
}

 DTO类:

public class InfoDTO  {
	
	private String email;
	
	public String getEmail() {
		email = ....(emial);//解密的伪代码
		return email;
	}

	public void setEmail(String email) {
		
		this.email = email;
	}
}

 这样,无论你访问多少次。数据库里的密文会一直保持,我们可以通过debug知道代码的执行顺序是:

Entity类的get方法从数据库里取出密文->DTO类的set方法把Entity类get到的值赋给自己->DTO类的get方法把自己get到的值做处理(直接显示或做处理)

从这个角度,可以将DTO类理解成一个数据的备份,不直接与数据库挂钩,也就不会影响数据库里的值

还有一种情景是UI输入查询/添加或修改去保存,这是一个与上面方向相反的过程。

此时DTO类可以用于收集form查询或添加/修改表单的数据,其实也可以用Map,看字段值的多少了。

同样,如果我们考虑email这个字段,用户输入的肯定是明文,存到数据库里需是密文,此时因为在Entity类里set方法直接是加密的了,所以我们要保持在DTO里get到的值是明文,执行顺序:

用户输入明文->DTO类的set方法来保存输入信息->DTO类的get方法来获得输入->Entity类的set方法加密

这时候我们会发现,如果在DTO类的get方法里还保留解密逻辑,就会出错,所以此时DTO的get方法又不能加了。

这就引申出一个问题,我们一般DTO当作Entity类和UI之间的介质,当他要作为接收参数的角色时,get方法里也不能加逻辑处理,此时需要注意!此时,我们只能用其他参数接收载体如Map

所以当字段需要做逻辑处理,不再是传统的get和set时,需要注意get和set对值的改变!

下面一张图是我对get和set的理解(图是用wps画的,很渣勿喷~)



 以上加解密只是一个例子,用于说明字段不再是单纯get和set时需要注意的地方!!!

猜你喜欢

转载自raising.iteye.com/blog/2338624