知识点:
1,hql是没有直接insert的语句
2,使用hibernate对数据库(postgresql)进行插入数据操作(法一:原生SQL的insert;法二:hibernate自带save方法)
3,设置主键自增
4,mapping报错Unknown Entity(情况一:设置@Entity映射是导错jar;情况二:未向配置文件cfg.xml加入映射文件hbm.xml;情况三:一个project里生成两个配置文件啊!!太愚蠢了我就是因为这个找了一天的bug最后在老师提点下才知道只需要建一个cfg.xml文件然后每次只需要添加映射的mapping语句即可)
以上具体解决法请看代码 ps:有彩蛋!
在次解释一下,通常情况下是利用hibernate自带的save()方法提交事务后即可向数据库中插入数据,但此处制作留言板需要主键id每插入一条就自增一次。如果每次使用save方法会导致主键值重复的问题,原因:
hibernate的save方法:当主键一样的时候,第二次调用save方法就是执行更新操作
彩蛋有该问题解决方法,对比起来使用原生SQL更方便
正式开始
数据库设计(表名:messa)
主键(id)自增:id数据类型设为serial
配置文件cfg.xml
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">org.postgresql.Driver</property>
<property name="hibernate.connection.password">password</property>
<property name="hibernate.connection.url">jdbc:postgresql://localhost:5432/jspdb?useUnicode=true&characterEncoding=UTF-8</property>
<property name="hibernate.connection.username">username</property>
<property name="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</property>
<!--重点-->
<property name="hibernate.temp.use_jdbc_metadata_defaults">false</property><!--用于解决报错Disabling contextual LOB creation as createClob() method threw err -->
<property name="show_sql">true</property><!--显示SQL语句-->
<property name="connection.autocommit">true </property>
<!--同一个项目不需要多次新建配置文件,在hibernate.cfg.xml里添加映射文件路径即可,否则mapping报错Unknown Entity-->
<mapping class="LoginUsers.beans.Users" resource="loginusers/beans/Users.hbm.xml"/>
<mapping class="LoginUsers.beans.Messas" resource="loginusers/beans/Messas.hbm.xml"/>
</session-factory>
</hibernate-configuration>
bean:
import javax.persistence.Entity; //一定注意不要导错这个包,如果导入的是org.hibernate带的会导致mapping报错Unknown Entity
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "messa")
public class Messas {
@Id //id映射位置不要写错。对应private int id
private int id;
private String mname;
private String subject;
private String memo;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getMname() {
return mname;
}
public void setMname(String mname) {
this.mname = mname;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getMemo() {
return memo;
}
public void setMemo(String memo) {
this.memo = memo;
}
}
Messas类 对应生成的映射文件hbm.xml
<hibernate-mapping>
<class name="loginusers.beans.Messas" table="MESSAS">
<id name="id" type="java.lang.String">
<column name="ID" />
<generator class="assigned" />
</id>
<property name="mname" type="java.lang.String">
<column name="MNAME" />
</property>
<property name="subject" type="java.lang.String">
<column name="SUBJECT" />
</property>
<property name="memo" type="java.lang.String">
<column name="MEMO" />
</property>
</class>
</hibernate-mapping>
Dao:
import java.sql.PreparedStatement;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import loginusers.beans.Messas;
public class MessasDao {
public void insertMsg(String mname,String subject,String memo) {
// StandardServiceRegistry registry = new StandardServiceRegistryBuilder().configure().build();
// SessionFactory sf = new MetadataSources( registry ).buildMetadata().buildSessionFactory();
// Session session = sf.openSession();
//
Session session =getSession();
session.beginTransaction();
//在hibernate中执行原生SQL的insert语句完成插入操作
String sql="insert into messa(mname,subject,memo) values(?,?,?)";
SQLQuery query = session.createSQLQuery(sql);
query.addEntity(Messas.class);
query.setString(0,mname);
query.setString(1,subject);
query.setString(2,memo);
query.executeUpdate();//提交至数据库
// Messas msg = new Messas();
// msg.setMname(mname);
// msg.setSubject(subject);
// msg.setMemo(memo);
//System.out.println(mname+""+subject+""+memo);
// session.save(msg);
//session.getTransaction().commit();//提交事务至数据库
session.close();
}
private Session getSession() {
StandardServiceRegistry registry = new StandardServiceRegistryBuilder().configure().build();
SessionFactory sf = new MetadataSources( registry ).buildMetadata().buildSessionFactory();
Session session = sf.openSession();
return session;
}
}
servlet:
public class savemsg extends HttpServlet {
private static final long serialVersionUID = 1L;
public savemsg() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html; charset=UTF-8");
PrintWriter out=response.getWriter();
String name=request.getParameter("name");
String subject=request.getParameter("subject");
String memo=request.getParameter("memo");
MessasDao mdao=new MessasDao();
mdao.insertMsg(name, subject,memo);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
jsp:
<html xmlns="http://www.w3.org/1999/xhtml">
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>留言板</title>
<script type="text/javascript">
$(function(){
$("#tijiao").click(function(){
var name=$("#name").val();
var subject = $("#subject").val();
var memo=$("#memo").val();
$.post("savemsg", {"name" : name,"subject":subject,"memo":memo}, function(msg) {
alert(msg);
});
alert("aa");});
$(".cz").click(function (){ //设置重置按钮,点击清空留言板
$("#memo").val('');
})
})
</script>
</head>
<body>
<h2><!-- 【${user.username}】 -->请发表你的留言</h2>
<div id="menu">
<p>昵称:<input type="text" id="name"></p>
<p>主题:<input type="text" id="subject"></p>
<p>内容:</p>
<p><textarea value="在这留言" style="width: 600px; height: 150px"id="memo">在这留言</textarea></p>
<p><input type="button" value="提交" id="tijiao"> <input type="button" value="重置" class="cz" ></p>
<p><h1>所有留言</h1></p>
<ul id="ul1">
</ul>
</div>
</body>
</html>
本地服务器运行jsp:
点击提交后数据库:
彩蛋:其实用save方法也是可以完成主键自增的插入,改两处即可,这里不赘述,上图。。。