• 前一次做个系统用的oracle数据库,使用hibernate生成主键的策略是SEQUENCE,当时觉得很累,因为不知道怎么的,oracle+sequence+trigger怎么也取不到新增数据时的主键值。   这次就把重点放这里了,...

    前一次做个系统用的oracle数据库,使用hibernate生成主键的策略是SEQUENCE,当时觉得很累,因为不知道怎么的,oracle+sequence+trigger怎么也取不到新增数据时的主键值。

     

    这次就把重点放这里了,同时还有两个新的问题,

    1。到底哪种hibernate生成主键的策略,性能优一点;

    2。主键生成策略最好是能跨数据库的。

     

     

    大家都说性能,oracle都是用的sequence,所以主键还是想用这个方式生成。

    接着就是返回新增数据的主键


    native
    根据底层数据库的能力选择 identity、sequence 或者 hilo 中的一个;

    也就是说,主键生成,由hibernate选择。

     

    对于内部支持标识字段的数据库(DB2、MySQL、Sybase 和 MS SQL),你可以使用 identity 关
    键字生成。对于内部支持序列的数据库(DB2、Oracle、PostgreSQL、Interbase、McKoi 和 SAP
    DB),你可以使用 sequence 风格的关键字生成。这两种方式对于插入一个新的对象都需要两次
    SQL 查询。

     

    查询了一下更多的网上资料,不知道在哪里看到了,这种生成主键的策略,如果是mysql,他会选择auto_increment方式生成主键;如果是oracle,他会选择sequence方式;只是在使用oracle数据库时,需要创建一个hibernate_sequence,这是hibernate保留的,不建会报错(测试过)。

     

    如下是完全的代码:

    Model:

     

    hibernate   mapping

     

     oracle表创建脚本:

     

    hibernate_sequence创建脚本

     

    Hibernate   DAO

     

    DAO  TEST  Base Class

     

    User DAO  Test

     

     

    spring bean

     

    完美的测试成功

     

     

     

     

     

    展开全文
  • hibernate中使用native SQL:能够返回多个实体对象,能够关联查询。

    hibernate提供了很多种查询方式,也支持原始的SQL查询。

    1.Scalar queries

    The most basic SQL query is to get a list of scalars (values).
    sess.createSQLQuery("SELECT * FROM CATS").list();
    sess.createSQLQuery("SELECT ID, NAME, BIRTHDATE FROM CATS").list();

    These will return a List of Object arrays (Object[]) with scalar values for each column in the CATS table. Hibernate will use ResultSetMetadata to deduce the actual order and types of the returned scalar values.

    To avoid the overhead of using ResultSetMetadata, or simply to be more explicit in what is returned, one can use addScalar():
    SQLQuery query = session.createSQLQuery(sql);
    query.addScalar("id", IntegerType.INSTANCE)
    		.addScalar("name", StringType.INSTANCE)
    		.addScalar("age", IntegerType.INSTANCE);

    也就是说:通过addScalar()显示地设置列的数据类型,能够避免hibernate自己使用ResultSetMetadata去检查数据库中列的实际类型,有一定的性能优势。不过这种方式一般没有啥用,我们虽然使用SQL,但还是希望返回值是对象,而不是Object[]。

     2.Entity queries

    The above queries were all about returning scalar values, basically returning the "raw" values from the resultset. The following shows how to get entity objects from a native sql query via addEntity().
    sess.createSQLQuery("SELECT * FROM CATS").addEntity(Cat.class);
    sess.createSQLQuery("SELECT ID, NAME, BIRTHDATE FROM CATS").addEntity(Cat.class);

    使用addEntity(),还可以设置表的别名:
    @Test
    public void test3() {
    	Session session = sessionFactory.openSession();
    
    	String sql = "select {c.*} from student {c}";
    
    	SQLQuery query = session.createSQLQuery(sql);
    	query.addEntity("c", Student.class);
    
    	System.out.println(query.list());
    }
    如果只是单表查询,这种设置别名的写法意义不大。但是如果查询多张表,而且这些表中存在同名字段,那么这种写法就很有必要了,能够帮助hibernate读取正确的列。

    @Test
    public void testMultiEntities() {
    	Session session = sessionFactory.openSession();
    
    	String sql = "select c.*, s.* from t_association_college c, t_association_student s where c.cid=s.college_id";
    
    	SQLQuery query = session.createSQLQuery(sql);
    	query.addEntity(College.class).addEntity(Student.class);
    
    	List<Object[]> results = (List<Object[]>) query.list();
    
    	System.out.println("validate whether lazy load.");
    
    	for (Object[] each : results) {
    		System.out.println("college=" + (College) each[0]);
    		System.out.println("student=" + (Student) each[1]);
    	}
    }
    这种写法,如果college表和student表没有重名的列,没有什么问题。最好使用下面这种写法,能够避免列重名等影响。
    @Test
    public void testAvoidRepeatName() {
    	Session session = sessionFactory.openSession();
    
    	String sql = "select {c.*}, {s.*} from t_association_college c, t_association_student s where c.cid=s.college_id";
    
    	SQLQuery query = session.createSQLQuery(sql);
    	query.addEntity("c", College.class).addEntity("s", Student.class);
    
    	List<Object[]> results = (List<Object[]>) query.list();
    
    	System.out.println("validate whether lazy load.");
    
    	for (Object[] each : results) {
    		System.out.println("college=" + (College) each[0]);
    		System.out.println("student=" + (Student) each[1]);
    	}
    
    	session.close();
    }

    3.Parameters

    Native SQL queries support positional as well as named parameters:
    Query query = sess.createSQLQuery("SELECT * FROM CATS WHERE NAME like ?").addEntity(Cat.class);
    List pusList = query.setString(0, "Pus%").list();
         
    query = sess.createSQLQuery("SELECT * FROM CATS WHERE NAME like :name").addEntity(Cat.class);
    List pusList = query.setString("name", "Pus%").list();         

    原始的JDBC占位符参数只能使用?,hibernate除了支持这种写法外,还支持命名参数。显然使用命名参数,可读性更好。

    4.associations

    College和Student配置了One-to-many单向关联,使用SQL一样可以关联查询:
    @Test
    public void testImmediateLoad() {
    	Session session = sessionFactory.openSession();
    
    	String sql = "select * from t_association_college c, t_association_student s where c.cid=s.college_id";
    
    	SQLQuery query = session.createSQLQuery(sql);
    	query.addEntity("c", College.class).addJoin("s", "c.allStudents");
    
    	List<Object[]> results = (List<Object[]>) query.list();
    
    	System.out.println("validate whether lazy load.");
    
    	for (Object[] each : results) {
    		System.out.println("college=" + (College) each[0]);
    		System.out.println("student=" + (Student) each[1]);
    	}
    
    	session.close();
    }


    虽然关联集合set没有懒加载,但是只发出了一条SQL语句就完成了查询,这种方式挺好。如果采用下面这种做法,会多查很多次数据库。这是为了查询college关联的student。
    @Test
    public void testAvoidRepeatName() {
    	Session session = sessionFactory.openSession();
    
    	String sql = "select {c.*}, {s.*} from t_association_college c, t_association_student s where c.cid=s.college_id";
    
    	SQLQuery query = session.createSQLQuery(sql);
    	query.addEntity("c", College.class).addEntity("s", Student.class);
    
    	List<Object[]> results = (List<Object[]>) query.list();
    
    	System.out.println("validate whether lazy load.");
    
    	for (Object[] each : results) {
    		System.out.println("college=" + (College) each[0]);
    		System.out.println("student=" + (Student) each[1]);
    	}
    
    	session.close();
    }




    展开全文
  • 本文作者:苏生米沿本文地址:翻译来源:http://stackoverflow.com/questions/20820880/hibernate-native-vs-hibernate-jpaHibernate 官方网站说,有native Hibernate API和 Hibernate 的JPA实现。在这两者之间有...

    本文作者:苏生米沿

    本文地址:http://blog.csdn.net/sushengmiyan/article/details/50182005

    翻译来源:http://stackoverflow.com/questions/20820880/hibernate-native-vs-hibernate-jpa

    Hibernate 官方网站说,有native Hibernate API和 Hibernate 的JPA实现。在这两者之间有什么区别呢?优势劣势都是什么?


    Hibernate website says there is a native Hibernate API as well as an implementation of JPA. What is the difference between the Native API and JPA implementation? Advantages, disadvantages?

    在使用Spring MVC构建应用程序的时候,使用tomcat做为服务器,使用mysql作为持久化数据库,对spring来说,我是新手,并且没有使用过Hibernate,我的团队想通过使用ORM方案,并且比较来说,Hibernate比较流行。现在不确定,Hibernate 是如何工作的?或者,我该使用native Hibernate或者是hibernate的JPA实现?应用程序是数据驱动的,实体和报表展示的。

    I am working on a Spring MVC application, using Tomcat as the container, and MySQL for persistence. I'm newer to Spring and never used Hibernate. My team would like to use an ORM and Hibernate seems to be the most popular. We're not sure how Hibernate is going to workout or whether we should use native or JPA api. The application will be data driven, data entry, reporting, etc.

    我知道,使用JPA的话,对于程序切换到另一个JPA实现会比较容易,尽管我不知道这样做是否是需要的。

    I've read that using JPA makes its easier to switch to another JPA implementation, although I don't know if that will be needed or not.

    JPA是通过ORM访问关系数据库的一个标准,Hibernate是它的一个实现。当年想使用JPA的时候,你需要使用它的一个实现,hibernate是一个不错的选择,但是还有其它实现,比如EclipseLink。

    JPA is a standard for accessing relational databases through an object oriented API. Hibernate is an implementation of this API. When you want to use JPA you need some vendor to implement it, Hibernate is a good choice but there are others like EclipseLink.

    Hibernate 存在的时间比JPA要长久。陈旧的native API仍然存在,并且提供一些标准的JPA没有提供的功能,如果你需要使用这些的话你就选择native API,使用JPA的话,就是更多程序员了解它,并且也可以通过配置来使用这些特性。

    Hibernate exists longer than JPA. The native, older API (which was a model for JPA) still exists, and sometimes it offers more possibilities than are exposed through JPA (e.g. orphan removal). If you need those you need to use the native API. Using JPA has other merits, most important (in my opinion) more developers that know it. And you still can use some Hibernate specifics through configuration.

    大多数的使用native hibernate的体验都是陈旧的,像Hibernate 3,是JPA的发行前版本.如果你是刚开始,建议使用JPA开始,尽管native的也有很多好的使用原由。

    Most tutorials that use Hibernate natively are quite old - as is Hibernate 3, a pre-JPA release. While there are good reasons to use it, they (IMO) typically don't apply to the general audience. So if you are just beginning to learn in this field I would suggest to start with JPA.

    作为线下资源,这里并没有何时的话题,你需要借鉴官方文档作为一个开始,并且至少从Hibernate4开始体验。

    As for recommendations on offsite resources: For good reasons they are not on topic here. But thecurrent official Hibernate documentation would be a good start, as would be to look for toturial for at least Hibernate 4.


    翻译来源:http://www.javabeat.net/jpa-entitymanager-vs-hibernate-sessionfactory/

    If you are using the JPA’s standard specification implementation (Read : Introduction to JPA), then you would use EntityManagerFactory for opening the session. But, if you are using the hibernate implementation, you have hibernate specific SessionFactory for managing the sessions. Here there is lot of confusion between developers like which one is the best approach. Here, there is two opinions are popular:

    如果你在使用标准的JPA实现的话,你可能会使用EntityManagerFactory来打开一个session,但是,如果你使用hibernate的实现的话,你使用hibernate的特定的SessionFactory来管理你的session,开发者在选择两者的时候有很多疑惑的,这里有两个主要观点:


    1. EntityManagerFactory is  the standard implementation, it is the same across all the implementations. If we migrate our ORM for any other provider, there will not be any change in the approach for handling the transaction. In contrast, if you use hibernate’s session factory, it is tied  to hibernate APIs and ca not migrate to new vendor easily.
    1.使用EntityManager是一个标准实现,你可以在所有实现中通用。如果我们更换其他ORM框架,不存在任何困难,但是你使用hibernate的话,那就绑定了,不能轻易的转换到其它实现了。

    2.One dis-advantage of using the standard implementation is that, it is not providing the advanced features. There is not much control provided in the EntityManager APIs. Whereas, hibernate’s SessionFactory has lot of advanced features which can not done in JPA. One such thing is retrieving the ID generator without closing the transaction, batch insert, etc.
    使用这个的一个缺点就是她不能提供一些hibernate的一些特性,比如,使用回本儿的SessionFactory不关闭事务来获取ID等。
    Looking into the above points, one has to decide which one is better. There is no hard rule, after all it depends on the developers requirement. Another suggestion is that, we can use entity manger and session factory together. In this approach, entity manage delegates session handling to the hibernate by invoking the unwrap method. Like this:
    比较而言,没有绝对的谁好谁不好,需要自己定夺。毕竟需要根据开发环境选择的,一个建议就是我们使用entitymager和sessionfactory一起,这样的话,我们就能融合两者了。
    可以通过如下方法切换:Session session = entityManager.unwrap(Session.class);
    Using EntityManagerFactory approach allows us to use callback method annotations like @PrePersist, @PostPersist,@PreUpdate with no extra configuration. Using similar callbacks while usingSessionFactory will require extra efforts.
    使用EntityManager可以让我们通过注解使用回调方法@PrePersist, @PostPersist,@PreUpdate而hibernate则需要额外的工作。

    展开全文
  • hibernate 框架下,mysql数据库 ,类型@a:=@a+1 的写法在hibernate的框架下会有问题 需要转义 类似于 \:参建http://blog.csdn.net/before_morning/article/details/51307137

    hibernate 框架下,mysql数据库 ,类型@a:=@a+1 的写法

    在hibernate的框架下会有问题 需要转义 类似于 \\:

    参建http://blog.csdn.net/before_morning/article/details/51307137

    展开全文
  • 最好的方式还是修改字段名称,如果不想修改字段名称,可以通过使用子查询的方式在表做关联之前,改变字段名称

    MySQL版本:5.6.19

    MySQL JDBC驱动版本:mysql-connector-java-5.1.30-bin

    Hibernate版本:3.6.0

    create table user (
      id int not null,
      name varchar(10),
      areaid int,
      primary key (id)
    );
    
    insert into user values(1, 'sean', 1);
    
    create table area (
      areaid int not null,
      name varchar(10),
      primary key (areaid)
    );
    
    insert into area values(1, 'Nanjing');

    hibernate.cfg.xml:

    <?xml version='1.0' encoding='utf-8'?>  
    <!DOCTYPE hibernate-configuration PUBLIC  
            "-//Hibernate/Hibernate Configuration DTD 3.0//EN"  
            "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">  
      
    <hibernate-configuration>  
        <session-factory>  
            <property name="show_sql">false</property>  
          
            <property name="dialect">org.hibernate.dialect.MySQLDialect</property>  
            <property name="connection.driver_class">com.mysql.jdbc.Driver</property>  
            <property name="connection.url">jdbc:mysql://127.0.0.1:3306/test</property>  
            <property name="connection.username">root</property>  
            <property name="connection.password">123456</property>  
        </session-factory>  
    </hibernate-configuration> 
    

    HibernateTest.java:

    package com.sean;
    
    import java.util.List;
    
    import org.hibernate.SQLQuery;
    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.hibernate.cfg.Configuration;
    
    public class HibernateTest {
    	public static void main(String[] args) {
    		Configuration conf = new Configuration();    
            SessionFactory sessionFactory = conf.configure().buildSessionFactory();    
            Session session = sessionFactory.openSession();    
            StringBuilder strB = new StringBuilder();
            strB.append("select u.name as userN, a.name as areaN ");
            strB.append("from user u left outer join area a ");
            strB.append("on u.areaid = a.areaid ");
            String sql = strB.toString(); 
            System.out.println(sql);
            SQLQuery query = session.createSQLQuery(sql);  
            List<Object[]> result = query.list();  
            for(Object[] objs : result)
            	System.out.println(objs[0] + " " + objs[1]);
    	}
    }
    

    执行结果如下:

    SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
    SLF4J: Defaulting to no-operation (NOP) logger implementation
    SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
    select u.name as userN, a.name as areaN from user u left outer join area a on u.areaid = a.areaid 
    Exception in thread "main" org.hibernate.exception.SQLGrammarException: could not execute query
    	at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:92)
    	at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
    	at org.hibernate.loader.Loader.doList(Loader.java:2536)
    	at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2276)
    	at org.hibernate.loader.Loader.list(Loader.java:2271)
    	at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:316)
    	at org.hibernate.impl.SessionImpl.listCustomQuery(SessionImpl.java:1842)
    	at org.hibernate.impl.AbstractSessionImpl.list(AbstractSessionImpl.java:165)
    	at org.hibernate.impl.SQLQueryImpl.list(SQLQueryImpl.java:157)
    	at com.sean.HibernateTest.main(HibernateTest.java:22)
    Caused by: java.sql.SQLException: Column 'name' not found.
    	at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1084)
    	at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:987)
    	at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:973)
    	at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:918)
    	at com.mysql.jdbc.ResultSetImpl.findColumn(ResultSetImpl.java:1162)
    	at com.mysql.jdbc.ResultSetImpl.getString(ResultSetImpl.java:5728)
    	at org.hibernate.type.descriptor.sql.VarcharTypeDescriptor$2.doExtract(VarcharTypeDescriptor.java:61)
    	at org.hibernate.type.descriptor.sql.BasicExtractor.extract(BasicExtractor.java:64)
    	at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:253)
    	at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:249)
    	at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:234)
    	at org.hibernate.loader.custom.CustomLoader$ScalarResultColumnProcessor.extract(CustomLoader.java:505)
    	at org.hibernate.loader.custom.CustomLoader$ResultRowProcessor.buildResultRow(CustomLoader.java:451)
    	at org.hibernate.loader.custom.CustomLoader.getResultColumnOrRow(CustomLoader.java:348)
    	at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:639)
    	at org.hibernate.loader.Loader.doQuery(Loader.java:829)
    	at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:274)
    	at org.hibernate.loader.Loader.doList(Loader.java:2533)
    	... 7 more
    

    实际上查询语句在MySQL中是可以正常执行的

    可以将查询语句中的别名去掉,程序可以正常运行,但是查询结果不正确

    select u.name, a.name from user u left outer join area a on u.areaid = a.areaid 
    sean sean

     

    解决方式:

    最好的方式还是修改字段名称,如果不想修改字段名称,可以通过使用子查询的方式在表做关联之前,改变字段名称

    select u.userN, a.areaN from (select name as userN, areaid from user) u left outer join (select areaid, name as areaN from area) a on u.areaid = a.areaid 
    sean Nanjing


    特意进行了验证以排除JDBC驱动的问题

    package com.sean;
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    import java.sql.Statement;
    
    public class JDBCTest {
    	public static void main(String[] args) throws Exception{
    		 Class.forName("com.mysql.jdbc.Driver");
             Connection conn = DriverManager.getConnection(  
                         "jdbc:mysql://127.0.0.1:3306/test",   
                         "root", 
                         "123456");   
             Statement stat =conn.createStatement(); 
             StringBuilder strB = new StringBuilder();
             strB.append("select u.name as userN, a.name as areaN ");
             strB.append("from user u left join area a ");
             strB.append("on u.areaid = a.areaid");
             String sql = strB.toString();
             System.out.println(sql);
             ResultSet rs = stat.executeQuery(sql);
             while(rs.next()){
            	 System.out.println(rs.getString(1) + " " + rs.getString(2));
             }
    	}
    }
    

    执行结果如下:

    select u.name as userN, a.name as areaN from user u left join area a on u.areaid = a.areaid
    sean Nanjing
    
    展开全文
  • Hibernate但是没有使用Hibernate的关联关系来进行数据库操作。所有的管理操作都是单独实现的。所以也不能用Criteria.add()这种方式去查询关联的一方。所以只能用Native SQL去查询结果返回对象了。按照Hibernate3的...
  • 有些时候,hibernate session.query()或者find没法执行一些原生的DB的一些函数或者...但是这样的话,总感觉不是特别好,不用spring的话,还得注意这个额外开的数据库连接的管理问题,hibernate提供了native sql查询
  • 最近在做一个签到的任务,由于要查询到历史连续最大签到记录的值,起初还是有点迷茫的--有一种想将查询结果查询出来,然后使用算法来解决这个问题。...回归到我需要讲解的问题--使用Hibernate 时,native sql中包含
  •  identity:由底层数据库生成标识符。identity是由数据库自己... increment:由hibernate管理主键,自动以递增的方式生成标识符,每次增量为1。其在每次插入前取得一个当前最大的id+1作为主键,该主键必须为Inte
  • 本文使用Hibernate3.2 cr2 1.直接返回List结果集,不包括列名信息 List ls = session.createSQLQuery(querySql).list(); 如果当前查询SQL里包括多列,则List里每行存放的是Object数组,如果直接查询的是一列,则...
  • 7.7 Hibernate:内置生成器 – native
  • Hibernate 是 DBA 最讨厌的框架之一, 在于 HQL 的滥用, 导致后期调优极度困难, 复杂的查询还是需要使用原生 SQL 来进行, 那么熟悉原生 SQL 调用就至关重要...
  • 针对mysql,native和increment的作用基本是一样的。 但是,native一定要求,表的id字段是自增的。increment则无要求。
  • hibernate在操作数据库时一般使用这3种id主键生成策略,native,assigned以及uuid.hex,我们在实体类映射文件student.hbm.xml中对这3种id主键策略进行讲解。第一种:assigned主键策略需要在添加数据时自己设置id,...
  • Hibernate从数据库中取出主键的最大值(每个session只取1次),以该值为基础,每次增量为1,在内存中生成主键,不依赖于底层的数据库,因此可以跨数据库。 Hibernate调用org.hibernate.id....
  • 如题,我们都理解hibernate不是万能的,被迫在很多地方应用nativeQuery 但nativeQuery是我们手写的,为了书写方便总是会写成select * from... 这样一来就失去了语句级别的自动优化 现在需要对sql查询进行优化处理,我...
  • <class name="com.hibernate.Users" table="students"> <generator class="native"/> bean: public class Users { private int sid; private String sname; private String gender; 省略...
  • 在使用spring MVC构建应用程序的时候,使用tomcat做为服务器,使用MySQL作为持久化数据库,对spring来说,我是新手,并且...或者,我该使用native Hibernate或者是hibernate的JPA实现?应用程序是数据驱动的,实体和
1 2 3 4 5 ... 20
收藏数 45,564
精华内容 18,225
关键字:

4 hibernate native