按照上一节的数据库设计 :   ​​mysql设计外键关联​

在Eclipse中创建工程名为(OneToMany)的JPA Project,创建的时候需要导入EclipseLink包。

配置persistence.xm文件


<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="OneToMany" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>model.Teacher</class>
<class>model.User</class>
<properties>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/tzx"/>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password" value="123456"/>
</properties>
</persistence-unit>
</persistence>


其中OneToMany为工程名,model为包名。

User.java


package model;

import java.io.Serializable;

import javax.persistence.*;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;


/**
* The persistent class for the user database table.
*
*/
@Entity
@NamedQuery(name="User.findAll", query="SELECT u FROM User u")
public class User implements Serializable {
private static final long serialVersionUID = 1L;

@Id
private String id;

private String pass;

//bi-directional many-to-one association to Teacher
@OneToMany(cascade = CascadeType.ALL,mappedBy="user" )//指向多的那方的pojo的关联外键字段
private Collection<Teacher> teachers = new ArrayList<Teacher>();

public User() {
}

public String getId() {
return this.id;
}

public void setId(String id) {
this.id = id;
}

public String getPass() {
return this.pass;
}

public void setPass(String pass) {
this.pass = pass;
}

public Collection<Teacher> getTeachers() {
return this.teachers;
}

public void setTeachers(Collection<Teacher> teachers) {
this.teachers = teachers;
}

public Teacher addTeacher(Teacher teacher) {
getTeachers().add(teacher);
teacher.setUser(this);

return teacher;
}

public Teacher removeTeacher(Teacher teacher) {
getTeachers().remove(teacher);
teacher.setUser(null);

return teacher;
}

}


Teacher.java


package model;

import java.io.Serializable;
import javax.persistence.*;


/**
* The persistent class for the teacher database table.
*
*/
@Entity
@NamedQuery(name="Teacher.findAll", query="SELECT t FROM Teacher t")
public class Teacher implements Serializable {
private static final long serialVersionUID = 1L;

@Id
private String name;

private String gender;

//bi-directional many-to-one association to User
@JoinColumn(name = "user_id")//设置对应数据表的列名和引用的数据表的列名
@ManyToOne(cascade=CascadeType.ALL)
private User user;

public Teacher() {
}

public String getName() {
return this.name;
}

public void setName(String name) {
this.name = name;
}

public String getGender() {
return this.gender;
}

public void setGender(String gender) {
this.gender = gender;
}

public User getUser() {
return this.user;
}

public void setUser(User user) {
this.user = user;
}

}


TestDAO.java封装数据操作


package simple;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;

import model.Teacher;
import model.User;

public class TestDAO {
private static final String PERSISTENCE_UNIT_NAME = "OneToMany";
private static EntityManagerFactory factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
EntityManager en = factory.createEntityManager();
public TestDAO(){

}
//增减信息
public void addUser(User user){
en.getTransaction().begin();
en.persist(user);
en.getTransaction().commit();
}
public void addTeacher(Teacher teacher){
en.getTransaction().begin();
en.persist(teacher);
en.getTransaction().commit();
}
//删除信息
public void removeUser(User user){
en.getTransaction().begin();
en.remove(user);
en.getTransaction().commit();
}
public void removeTeacher(Teacher teacher){
en.getTransaction().begin();
en.remove(teacher);
en.getTransaction().commit();
}
public void deleteUser(){
en.getTransaction().begin();
String deleteQL="delete from User";
Query deleteQuery=en.createQuery(deleteQL);
deleteQuery.executeUpdate();
en.getTransaction().commit();
}
public void deleteTeacher(){
en.getTransaction().begin();
String deleteQL="delete from Teacher";
Query deleteQuery=en.createQuery(deleteQL);
deleteQuery.executeUpdate();
en.getTransaction().commit();
}
//更新信息
public void updateUser(User user){
en.getTransaction().begin();
String sql = "update User u set u.pass='" + user.getPass() + "' where u.id='" + user.getId() + "'";
en.createQuery(sql).executeUpdate();
en.refresh(user);
en.getTransaction().commit();
}
public void updateTeacher(Teacher teacher){
en.getTransaction().begin();
en.refresh(teacher);
en.getTransaction().commit();
}
//查询信息
public List<User> getAllUsers(){
en.getTransaction().begin();
List<User> userList = en.createQuery("SELECT u FROM User u").getResultList();
en.getTransaction().commit();
return userList;
}
public List<Teacher> getAllTeachers(){
en.getTransaction().begin();
List<Teacher> teacherList = en.createQuery("SELECT t FROM Teacher t").getResultList();
en.getTransaction().commit();
return teacherList;
}
public List<User> getUsers(String sql){
en.getTransaction().begin();
List<User> userList = en.createQuery(sql).getResultList();
en.getTransaction().commit();
return userList;
}
}


TestJDBC.java


package simple;

import java.util.Iterator;
import java.util.List;

import model.Teacher;
import model.User;

public class TestJDBC {
public static void showUserList(List<User>list){
System.out.println("-----用户 列表-----");

for(Iterator<User> i=list.iterator();i.hasNext();){
User user=i.next();
System.out.print(user.getId()+": "+user.getPass()+ ",老师有:");
for(Iterator<Teacher> j=user.getTeachers().iterator();j.hasNext();){
Teacher teacher = j.next();
System.out.print(teacher.getName() + "-");
}
System.out.println();
}
}
public static void showTeacherList(List<Teacher>list){
System.out.println("-----用户 列表-----");

for(Iterator<Teacher> i=list.iterator();i.hasNext();){
Teacher teacher=i.next();
System.out.println(teacher.getName()+": "+teacher.getGender()+ ",学生为:" + teacher.getUser().getId() + "\n");
}
}
public static void showMessage(){
TestDAO tDao = new TestDAO();
//显示所有老师信息
System.out.println("显示所有老师信息~!");
showTeacherList(tDao.getAllTeachers());
//显示所有User信息
System.out.println("显示所有User信息~!");
showUserList(tDao.getAllUsers());
}
public static void main(String[] args){
TestDAO testDAO = new TestDAO();
System.out.println("所有数据清理~!");
//删除所有User和Teacher信息
testDAO.deleteUser();
testDAO.deleteTeacher();
User temp1 = new User();
temp1.setId("小明");
temp1.setPass("111111");
User temp2 = new User();
temp2.setId("小六");
temp2.setPass("222222");
//添加user信息
testDAO.addUser(temp1);
testDAO.addUser(temp2);
//显示所有User信息
System.out.println("显示所有User信息~!");
showUserList(testDAO.getAllUsers());

Teacher tea1 = new Teacher();
Teacher tea2 = new Teacher();
tea1.setName("数学");
tea1.setGender("男");
tea2.setName("英语");
tea2.setGender("女");
Teacher tea3 = new Teacher();
Teacher tea4 = new Teacher();
tea3.setName("化学");
tea3.setGender("男");
tea4.setName("物理");
tea4.setGender("女");
//添加Teacher信息
testDAO.addTeacher(tea1);
testDAO.addTeacher(tea2);
testDAO.addTeacher(tea3);
testDAO.addTeacher(tea4);
temp1.addTeacher(tea1);
temp1.addTeacher(tea2);
temp2.addTeacher(tea3);
temp2.addTeacher(tea4);
// testDAO.addTeacher(tea1);
// testDAO.addTeacher(tea2);
// testDAO.addTeacher(tea3);
// testDAO.addTeacher(tea4);
testDAO.addUser(temp1);
testDAO.addUser(temp2);
showMessage();
//连级查询JPAL语言
String sql = "select u from User u,in (u.teachers) t where t.name = '化学'";
List<User> temp = testDAO.getUsers(sql);
System.out.println("化学老师的学生为:" + temp.get(0).getId() + ":" + temp.get(0).getPass());
//修改小六信息
temp2.setPass("xiaoliu");
testDAO.updateUser(temp2);
showMessage();
//删除小六信息
testDAO.removeUser(temp2);
showMessage();
}
}


cascade = CascadeType.ALL可以解释为:


CascadeType.REFRESH:级联刷新,也就是说,当你刚开始获取到了这条记录,那么在你处理业务过程中,这条记录被另一个业务程序修改了(数据库这条记录被修改了),那么你获取的这条数据就不是最新的数据,那你就要调用实体管理器里面的refresh方法来刷新实体,所谓刷新,大家一定要记住方向,它是获取数据,相当于执行select语句的(但不能用select,select方法返回的是EntityManager缓存中的数据,不是数据库里面最新的数据),也就是重新获取数据。 

CascadeType.PERSIST:级联持久化,也就是级联保存。保存User的时候也保存Teacher,如果在数据库里已经存在与需要保存的Teacher相同的name记录,则级联保存出错。

CascadeType.MERGE:  级联更新,也可以叫级联合并;当对象User处于游离状态时,对对象User里面的属性作修改,也修改了User里面的Teacher,当要更新对象User时,是否也要把对Teacher的修改同步到数据库呢?这就是由CascadeType.MERGE来决定的,如果设了这个值,那么User处于游离状态时,会先update User,然后for循环update Teacher,如果没设CascadeType.MERGE这个值,就不会出现for循环update Teacher语句。所以说,级联更新是控制对User的更新是否会波及到Teacher对象。也就是说对User进行update操作的时候,Teacher是否也要做update操作呢?完全是由CascadeType.MERGE控制的。

CascadeType.REMOVE:当对User进行删除操作的时候,是否也要对Teacher对象进行级联删除操作呢?是的则写,不是的则不写。