映射实体Bean的关联关系
一对一(One-to-one)
使用@OneToOne注解可以建立实体bean之间的一对一的关联. 一对一关联有三种情况: 一是关联的实体都共享同样的主键, 二是其中一个实体通过外键关联到另一个实体的主键 (注意要模拟一对一关联必须在外键列上添加唯一约束). 三是通过关联表来保存两个实体之间的连接关系 (注意要模拟一对一关联必须在每一个外键上添加唯一约束).
1,共享主键来进行一对一关联映射:
使用注解@PrimaryKeyJoinColumn定义了一对一关联.
@OneToOne(cascade = CascadeType.ALL)
@PrimaryKeyJoinColumn
2, 使用外键列进行实体的关联.
@Entity public class Customer implements Serializable { @OneToOne(cascade = CascadeType.ALL) @JoinColumn(name="passport_fk") public Passport getPassport() { ... }
@Entity public class Passport implements Serializable { @OneToOne(mappedBy = "passport") public Customer getOwner() { ... }
|
上面这个例子中,Customer 通过Customer 表中名为的passport_fk 外键列和 Passport关联. @JoinColumn注解定义了联接列(join column). 该注解和@Column注解有点类似, 但是多了一个名为referencedColumnName的参数. 该参数定义了所关联目标实体中的联接列. 注意,当referencedColumnName关联到非主键列的时候, 关联的目标类必须实现Serializable, 还要注意的是所映射的属性对应单个列(否则映射无效).
一对一关联可能是双向的.在双向关联中, 有且仅有一端是作为主体(owner)端存在的:主体端负责维护联接列(即更新). 对于不需要维护这种关系的从表则通过mappedBy属性进行声明. mappedBy的值指向主体的关联属性. 在上面这个例子中,mappedBy的值为 passport. 最后,不必也不能再在被关联端(ownedside)定义联接列了,因为已经在主体端进行了声明.
如果在主体没有声明@JoinColumn,系统自动进行处理: 在主表(owner table)中将创建联接列, 列名为:主体的关联属性名+下划线+被关联端的主键列名. 在上面这个例子中是passport_id,因为Customer中关联属性名为passport, Passport的主键是id.
多对一(Many-to-one)
在实体属性一级使用@ManyToOne注解来定义多对一关联:
@Entity() public class Flight implements Serializable { @ManyToOne( cascade = {CascadeType.PERSIST, CascadeType.MERGE} ) @JoinColumn(name="COMP_ID") public Company getCompany() { return company; } ... } |
其中@JoinColumn是可选的,关联字段默认值和一对一 (one to one)关联的情况相似, 列名为:主体的关联属性名+下划线+被关联端的主键列名. 在这个例子中是company_id,因为关联的属性是company, Company的主键是id.
一对多(One-to-many)
在属性级使用 @OneToMany注解可定义一对多关联.一对多关联可以是双向关联.
双向(Bidirectional)
@Entity public class Troop { @OneToMany(mappedBy="troop") public Set<Soldier> getSoldiers() { ... }
@Entity public class Soldier { @ManyToOne @JoinColumn(name="troop_fk") public Troop getTroop() { ... } |
单向(Unidirectional)
@Entity public class Customer implements Serializable { @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER) @JoinColumn(name="CUST_ID") public Set<Ticket> getTickets() { ... }
@Entity public class Ticket implements Serializable { ... //no bidir }
|
Customer 通过 CUST_ID列和Ticket 建立了单向关联关系
通过关联表处理单向关联
@Entity public class Trainer { @OneToMany @JoinTable( name="TrainedMonkeys", joinColumns = { @JoinColumn( name="trainer_id") }, inverseJoinColumns = @JoinColumn( name="monkey_id") ) public Set<Monkey> getTrainedMonkeys() { ... }
@Entity public class Monkey { ... //no bidir }
|
Trainer通过 TrainedMonkeys表和 Monkey 建立了单向关联. 其中外键trainer_id关联到Trainer (joinColumns), 而外键monkey_id关联到 Monkey (inversejoinColumns).
多对多(Many-to-many)
你可以通过@ManyToMany注解可定义的多对多关联. 同时,你也需要通过注解@JoinTable描述关联表和关联条件. 如果是双向关联,其中一段必须定义为owner,另一端必须定义为inverse(在对关联表进行更新操作时这一端将被忽略):
@Entity public class Store { @ManyToMany(cascade = CascadeType.PERSIST) public Set<City> getImplantedIn() { ... } }
@Entity public class City { ... //no bidirectional relationship }
|
双向
@Entity public class Store { @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}) public Set<Customer> getCustomers() { ... } }
@Entity public class Customer { @ManyToMany(mappedBy="customers") public Set<Store> getStores() { ... } }
|
这里常用的方法是生成中间表。配置了级联映射后,不会直接去操作中间表,而是通过操作主表去间接操作中间表。中间表的增、删、改都是通过主表的update实现的,如下面例子:用户添加权限或更新,则Role role=sessin.get(Role.class,rid);user.setRole(role);如果是删除权限,直接Role role=new Role()即可。中间表的查找操作则是主表的get方法来获取。如获取用户权限,直接user.getRole()。
举例:用户权限登录:
一个用户只能拥有一个角色,用户和角色为多对一关系,角色和权限为多对多关系。
1、实体类:
(1、)用户
package com.ifytek.domain;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
@Entity
@Table(name="userlogin")
@SequenceGenerator(name="seq_userlogin",sequenceName="seq_userlogin",allocationSize=1)
public class User {
private int id;
private String name;
private String pwd;
private String realname;
private String sex;
private String birthday;
private String idnum;
private String phone;
private String email;
private Role role=new Role();
@ManyToOne
@JoinTable(name = "user_role", joinColumns = {
@JoinColumn(name = "lid") }, inverseJoinColumns = @JoinColumn(name = "rid"))
public Role getRole() {
return role;
}
public void setRole(Role role) {
this.role = role;
}
@Id
@GeneratedValue(strategy=GenerationType.AUTO,generator="seq_userlogin")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public String getRealname() {
return realname;
}
public void setRealname(String realname) {
this.realname = realname;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getBirthday() {
return birthday;
}
public void setBirthday(String birthday) {
this.birthday = birthday;
}
public String getIdnum() {
return idnum;
}
public void setIdnum(String idnum) {
this.idnum = idnum;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public String toString() {
return "User [name=" + name + "]";
}
}
(2、)角色:
package com.ifytek.domain;
import java.io.Serializable;
import javax.persistence.JoinColumn;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.Table;
@Entity
@Table(name="t_role")
public class Role implements Serializable{
private int id;
private String name;
private List<Menu> menulist=new ArrayList<>();
private List<User> user=new ArrayList<>();
@OneToMany(mappedBy="role",fetch=FetchType.EAGER)
public List<User> getUser() {
return user;
}
public void setUser(List<User> user) {
this.user = user;
}
@ManyToMany(fetch=FetchType.EAGER)
@JoinTable(name="role_menu",joinColumns=@JoinColumn(name="rid"),inverseJoinColumns=@JoinColumn(name="mid"))
public List<Menu> getMenulist() {
return menulist;
}
public void setMenulist(List<Menu> menulist) {
this.menulist = menulist;
}
@Id
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Role [id=" + id + ", name=" + name + ", menulist=" + menulist + ", user=" + user + "]";
}
}
(3、)权限(即菜单):
package com.ifytek.domain;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import javax.persistence.Transient;
@Entity
@Table(name="menu")
public class Menu implements Serializable{
private int id;
private int pid;
private String urls;
private String name;
private ArrayList<Menu> children = new ArrayList<>();
private List<Role> role=new ArrayList<>();
// @ManyToMany(mappedBy="menulist")
public List<Role> getRole() {
return role;
}
public void setRole(List<Role> role) {
this.role = role;
}
@Id
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getPid() {
return pid;
}
public void setPid(int pid) {
this.pid = pid;
}
public String getUrls() {
return urls;
}
public void setUrls(String urls) {
this.urls = urls;
}
@Transient
public ArrayList<Menu> getChildren() {
return children;
}
public void setChildren(ArrayList<Menu> children) {
this.children = children;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Menu() {
super();
// TODO Auto-generated constructor stub
}
public Menu(int id, int pid, String urls, String name) {
//super();
this.id = id;
this.pid = pid;
this.urls = urls;
this.name = name;
}
@Override
public String toString() {
return "Menu [name=" + name + "]";
}
}
2、前台
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" type="text/css" href="assets/themes/default/easyui.css">
<link rel="stylesheet" type="text/css" href="assets/themes/icon.css">
<link rel="stylesheet" type="text/css" href="assets/css/all.css">
<script type="text/javascript" src="assets/jquery.min.js"></script>
<script type="text/javascript" src="assets/jquery.easyui.min.js"></script>
<script>
$(function(){
$("form").submit(function(){
var dt=$("form").serialize();
$.post("login",dt,function(data){
//alert(data);
if(data=="登录成功"){
window.location.href="main";
}else{
alert(data);
}
});
return false;
})
})
</script>
<style type="text/css">
* {
margin: 0;
padding: 0;
}
.container {
width: 80%;
margin: 0 auto;
}
#header {
width: 1130px;
height: 100px;
background-color: darkgrey;
margin: 0 auto;
text-align: center;
}
#content {
width: 1130px;
margin: 0 auto;
}
#left {
width: 700px;
height: 650px;
background-color: white;
float: left;
}
#right {
height: 650px;
float: left;
width: 430px;
background-color: lightgray;
}
form {
width: 80%;
margin: 0 auto;
margin-top: 200px;
}
form input {
margin-top: 20px;
height: 40px;
font-size: 20px;
width: 300px;
}
.registerdiv{
width:500px;
height:500px;
background-color: wheat;
position: absolute;
top:100px;
left:200px;
}
.left_top{
width:100%;
height:10%}
.left_mid{
width:100%;
height:50%;
//background-color: #0099FF;}
.dg{
width: 100%;
height: 100%;
}
.left_bottom{
width:100%;
height:50%;
//background-color: #0099FF;}
.img{
width:100%;
height:100%;}
.header1{
height:15%;}
.header2{
height:85%;
float:left;}
</style>
</head>
<body>
<div id="header">
<div class="header1"><h1>欢迎使用设备报修系统</h1></div>
<div class="header2"><iframe allowtransparency="true" frameborder="0" width="385" height="96" scrolling="no" src="//tianqi.2345.com/plugin/widget/index.htm?s=1&z=1&t=0&v=0&d=3&bd=0&k=&f=<f=009944&htf=cc0000&q=1&e=1&a=1&c=71879&w=385&h=96&align=left"></iframe>
</div>
</div>
<div id="content">
<div id="left">
<!-- <div class="left_bottom"> -->
<img src="assets/img/main.png" class="img">
</div>
<!-- 登录 -->
<div id="right" name="right" class="right">
<form method="post">
<input type="text" name="username" placeholder="请输入用户名" /><br /> <input
type="password" name="pwd" placeholder="请输入密码" /><br /> <input
type="text" name="authcode" placeholder="请输入验证码" /> <img
src="getImg" οnclick="this.src='getImg?authCode=' + Math.random();"
> <br /> <input type="submit" value="登录" /><br>
<a href='register' >还没有账号,马上注册</a>
</form>
</div>
</div>
</body>
</html>
首页:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>欢迎</title>
<link rel="stylesheet" href="assets/css/zTreeStyle/zTreeStyle.css" type="text/css">
<link rel="stylesheet" href="assets/css/home.css" type="text/css">
<script type="text/javascript" src="assets/js/jquery-1.4.4.min.js"></script>
<script type="text/javascript" src="assets/js/jquery.ztree.core.js"></script>
<style>
.box {
position: absolute;
top: 200px;
left: 200px;
width: 300px;
height: 300px;
display: none;
border: 1px solid antiquewhite;
}
input {
margin: 20px;
}
a {
text-decoration: none;
}
.div1 {
float: right;
margin: 2px;
}
.div2 {
float: right;
margin: 2px;
}
.box {
height: 350px;
top: 0px
}
</style>
<SCRIPT type="text/javascript">
var setting = {
view: {
dblClickExpand: false,
showLine: true,
selectedMulti: false,
showIcon: true,
addDiyDom: addDiyDom
},
async: {
enable: true,
url: "getmenu", //请求树形组件
},
callback: {
beforeClick: function(treeId, treeNode) {
var zTree = $.fn.zTree.getZTreeObj("treeDemo");
if(treeNode.isParent) {
zTree.expandNode(treeNode);
return false;
} else {
demoIframe.attr("src", treeNode.urls);
return true;
}
}
}
};
$(document).ready(function() {
var t = $("#treeDemo");
$.fn.zTree.init(t, setting);
demoIframe = $("#testIframe");
demoIframe.bind("load", loadReady);
});
function loadReady() {
var bodyH = demoIframe.contents().find("body").get(0).scrollHeight,
htmlH = demoIframe.contents().find("html").get(0).scrollHeight,
maxH = Math.max(bodyH, htmlH),
minH = Math.min(bodyH, htmlH),
h = demoIframe.height() >= maxH ? minH : maxH;
if(h < 530) h = 530;
demoIframe.height(h);
}
function addDiyDom(treeId, treeNode) {
var spaceWidth = 5;
var switchObj = $("#" + treeNode.tId + "_switch"),
icoObj = $("#" + treeNode.tId + "_ico");
switchObj.remove();
icoObj.before(switchObj);
if(treeNode.level > 1) {
var spaceStr = "<span style='display: inline-block;width:" + (spaceWidth * treeNode.level) + "px'></span>";
switchObj.before(spaceStr);
}
}
var name;
$.post("main", function(data) {
name = data;
$("#name").html(data);
})
function exit() {
var a = confirm("确定退出吗?");
if(a) {
window.location.href = "exit";
}
}
//隐藏的修改密码div
function msgbox(n) {
if(n == 0) {
$(".box").css("display", "none");
} else {
$(".box").css("display", "block");
}
}
function updatepwd() {
msgbox(1);
}
function fun() {
var bepwd = $("#bepwd").val();
var npwd = $("#npwd").val();
var npwd1 = $("#npwd1").val();
if(bepwd == "" || npwd == "" || npwd1 == "") {
alert("密码不可以为空");
} else if(npwd != npwd1) {
alert("两次输入密码不相等");
} else {
var dt = "&name=" + name + "&pwd=" + npwd;
$.post("updatepwd", dt, function(data) {
alert(data);
if(data=="修改成功"){
window.location.href = "exit";
}
})
}
}
</SCRIPT>
</head>
<body>
<div id="header">
<div class="div1">
<a href="exit" target="_top">退出登录</a>
</div>
<div class="div2"><button οnclick="updatepwd()">修改密码</button></div>
<h1>欢迎您,<div id="name" ></h1></div>
<!-- 修改密码div -->
<div class="box">
<a class='x' href='' ; οnclick="msgbox(0); return false;">关闭</a><br> 原 密 码:
<input type="password" name="bepwd" id="bepwd" /><br /> 新 密 码:
<input type="password" name="npwd" id="npwd" /><br /> 确认密码:
<input type="password" name="npwd1" id="npwd1" /><br />
<input type="button" value="提交" οnclick="fun()" />
</div>
</div>
<div id="content">
<TABLE border=0 height=650px align=left>
<TR>
<TD width=260px align=left valign=top style="BORDER-RIGHT: #999999 1px dashed">
<ul id="treeDemo" class="ztree" style="width:260px; overflow:auto;"></ul>
</TD>
<TD width=1130px align=left valign=top>
<IFRAME ID="testIframe" Name="testIframe" FRAMEBORDER=0 SCROLLING=AUTO width=100% height=700px SRC="welcome"></IFRAME>
</TD>
</TR>
</TABLE>
</div>
</body>
</html>
3、后台:
package com.ifytek.controller;
import java.io.IOException;
import java.net.URLEncoder;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import com.ifytek.domain.Message;
import com.ifytek.domain.User;
import com.ifytek.service.UserService;
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("login post");
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
String username = req.getParameter("username");
String pwd = req.getParameter("pwd");
String code = req.getParameter("authcode");
String authcode = (String) req.getSession().getAttribute("authCode");
User user = new User();
user.setName(username);
user.setPwd(pwd);
if (authcode.equals(code)) {
UserService service=new UserService();
Message message = service.checkLogin(user);
System.out.println(message.getMsg());
if(message.isRes()){
HttpSession httpSession=req.getSession();
httpSession.setAttribute("username", username);
username=URLEncoder.encode(username, "utf-8");
Cookie cookie=new Cookie("username", username);
cookie.setMaxAge(60*60);
resp.addCookie(cookie);
}
resp.getWriter().write(message.getMsg());
} else {
resp.getWriter().write("验证码错误");
}
}
}
package com.ifytek.controller;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import com.ifytek.service.UserService;
@WebServlet("/getmenu")
public class GetMenuServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
HttpSession session=req.getSession();
String username=(String) session.getAttribute("username");
UserService service=new UserService();
String menujson=service.getMenuJson(username);
//System.out.println(menujson);
resp.getWriter().write(menujson);
}
}
4、获取树形组件service:
public String getMenuJson(String username) {
UserDao dao=new UserDao();
int uid=getIdByName(username);
List<Menu> menus = dao.getMenuByUserId(uid);
System.out.println("获取的list集合为"+menus);
System.out.println("获取的list集合长度为"+menus.size());
ArrayList<Menu> fmenu = new ArrayList<>();
for (Menu menu : menus) {
if (menu.getPid() == 0) {
// 一级菜单
//System.out.println("..." + menu.getId());
//System.out.println("一级菜单: " + menu.getName());
fmenu.add(menu);
} else {
// 非一级菜单
}
}
for (Menu menu : menus) {
if (menu.getPid() != 0) {
//System.out.println("。。。" + menu.getId());
for (Menu fm : fmenu) {
if (menu.getPid() == fm.getId()) {
fm.getChildren().add(menu);
}
}
}
}
System.out.println(fmenu);
String json=JSON.toJSONString(fmenu,true);
return json;
}
dao:
public List<Menu> getMenuByUserId(int uid) {
//System.out.println("用户id为"+uid);
Session session=HibernateUtil.getSessionFactory().openSession();
String hql="from User u where u.id=?";
Query query=session.createQuery(hql);
query.setInteger(0, uid);
User user=(User) query.uniqueResult();
List<Menu> list=(List<Menu>) user.getRole().getMenulist();
//ArrayList<Menu> list= (ArrayList<Menu>) ;
//System.out.println("list为"+list.size());
session.close();
return list;
}