1. Background of the problem
Personally prefer spring data JPA, this time the problem is to use the list type as a field in the entity class, JPA also provides a way to operate, that is, using @elementcollection annotations, the online knowledge of JPA is fragmented, After all, it's not as easy to use as MyBatis.
To get to the bottom, take a look at the fields in my entity class:
@ElementCollection(fetch = FetchType.LAZY)//定义基本类型或可嵌入类的实例集合 @OrderColumn(name="position")//如果使用的是List,你需要多定义一个字段维护集合顺序 private List<String> part;
In fact, JPA internal fields for collection types are maintained using a different table. Simply put, you save yourself from defining another table to maintain a one-to-many relationship.
So, I would like to update this table of this field can not be like updating the normal field (String,int), it is not the same?
The JPA update field is available in two ways, one by setting the primary key for Save () and one by @query annotations.
If we use the second type, we have already said that in fact is the operation of the other table, so we just need to change the other table and other changes to be good.
But this person feels a little bit out of the JPA personality, so I want to use the first one.
But there are two problems with the first approach:
- Part of the entity class lazy lazy loading will cause this part of the field to be null after the update?
- Why does JPA know that our call to save () method is Updata update instead of insert new?
Take a look at the test cases below.
2. Test Cases
The following is the definition of the entity class, mainly by the primary key ID, the field name, and the collection part, the collection for lazy lazy loading.
@Entity@Table(name = "name_href")public class NameHref { @Id @GeneratedValue() private int id; @Column(name = "name") private String name; private String href; @ElementCollection(fetch = FetchType.LAZY) @OrderColumn(name="position") private List<String> part; ......
When we define the set part for lazy lazy loading, it is normal to use JPA to get the entity after the value is not taken, (execution of the Get method will error) So after updating the field the value is not NULL, we look at the unit test:
@Autowired NameHrefRepository nameHrefRepository; @Test public void getHref() { NameHref nameHref = new NameHref(); nameHref.setId(-1); String name = "博客园"; nameHref.setName(name); nameHref.setHref("http://www.cnblogs.com"); ArrayList<String> objects = new ArrayList<>(); objects.add("安卓"); objects.add("苹果"); nameHref.setPart(objects); nameHrefRepository.save(nameHref); NameHref byName = nameHrefRepository.findAllByName(name); byName.setHref("http://www.baidu.com"); nameHrefRepository.save(byName); }
This code is to create a new entity to save to the database and then get the entity, modify some fields, save using the Save () method. After execution we look at the database field: The HREF attribute has been successfully modified, and the collection that is declared as lazy is also in. Indicates that the Save () method performed the Updata operation correctly. So what exactly does JPA do, look at the SQL records:
Hibernate: select namehref0_.id as id1_20_, namehref0_.href as href2_20_, namehref0_.name as name3_20_ from name_href namehref0_ where namehref0_.name=?Hibernate: select namehref0_.id as id1_20_0_, namehref0_.href as href2_20_0_, namehref0_.name as name3_20_0_ from name_href namehref0_ where namehref0_.id=?Hibernate: update name_href set href=?, name=? where id=?
A total of three SQL is executed, the first sentence is the query operation performed by the Find method, and the third sentence of the second sentence is the operation by the Save () method. It can be concluded that the JPA update field is about the principle of executing the SELECT statement to determine if the data already exists, and if so, execute the UPDATA statement for the update operation. How does the JPA resolve the Save () operation? The answer is whether the primary key is assigned a value. Consider the following test methods:
NameHref nameHref = new NameHref();// nameHref.setId(-1); String name = "博客园"; nameHref.setName(name); nameHref.setHref("http://www.cnblogs.com"); nameHrefRepository.save(nameHref);
The above code comments out the SetID () method, executes the program, and looks at the SQL print:
Hibernate: insert into name_href (href, name) values (?, ?)
Only the INSERT statement is executed, so the JPA's Save () method for the program call determines whether the Updata or insert operation is based on seeing if the primary key of the entity object is assigned a value.
It's not over yet, if you're not getting the entity object through repository, but you're defining the entity object yourself and assigning a value to the primary key, you want to update the part of the field, then you update the field by using the Save () method, and the undefined fields appear null. Consider the following test cases:
NameHref nameHref = new NameHref(); nameHref.setId(1); String name = "博客园2号"; nameHref.setName(name); nameHrefRepository.save(nameHref);
In the above code, we want to reach the value of the name field with ID 1 in the Update data table and keep the values of the other fields intact. After executing the program, we look at the data sheet:
In addition to the field Id,name (name being successfully modified), the other fields become null, which is why? Take a look at the SQL execution record:
Hibernate: select namehref0_.id as id1_20_0_, namehref0_.href as href2_20_0_, namehref0_.name as name3_20_0_ from name_href namehref0_ where namehref0_.id=?Hibernate: update name_href set href=?, name=? where id=?Hibernate: delete from name_href_part where name_href_id=?
Looking at SQL printing, we know that JPA first makes a pre-update decision to see if it already exists. And then the update operation, but at this time the JPA does not seem so smart, it does not know that we just want to update some of the fields, but instead of updating all the fields, so that we do not assign the value of the other fields are null, and actively delete the associated table field part. As a result, it is not advisable to manually create a new entity object and perform an update operation.
3, sum up a wave
The JPA update field is available in two ways, one by setting the primary key for Save () and one by @query annotations.
Update fields using the Save () method Be sure to get the entity object through repository and update on this object.
Recommend me another article: Two lines of code play spring data sorting and paging