1

我正在使用 Hibernate 3.5.6-Final、Spring 3.0.5 和 HSQLDB 2.2.9。我们公司在真实数据库上使用 Microsoft SQL 2008。我想从真实的数据库中分离出来,通过脚本创建一个虚拟的 HSQLDB 数据库用于 jUnit 测试。在 HSQL 数据库管理器中,我创建了 DBA 模式和一个表用户,接下来用一个用户填充它 - arnold_foukal(用户名)。接下来我执行 SHUTDOWN 命令并正确创建了脚本。我尝试在 HSQL 数据库管理器中选择这个用户名,它可以工作!

但现在我想把它集成到我的项目中:

1) ApplicationContext.xml

    <bean id="userDao" class="cz.mbaf.security.dao.impl.UserDaoImpl" >
        <property name="sessionFactory" ref="sessionFactory2"/>
    </bean>

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">        
        <property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
        <property name="url" value="jdbc:hsqldb:file:testdb;shutdown=true"/>
        <property name="username" value="SA"/>
        <property name="password" value=""/>
        <property name="maxActive" value="100"/>
        <property name="maxWait" value="50"/>
        <property name="poolPreparedStatements" value="true"/>
        <property name="defaultAutoCommit" value="false"/>
    </bean>

    <!-- Hibernate Session Factory  -->
    <bean id="sessionFactory2" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="dataSource" ref="proxyDataSource" />
        <property name="configurationClass">
            <value>org.hibernate.cfg.AnnotationConfiguration</value>
        </property>
        <property name="configLocation">
            <value>classpath:hibernate.cfg.xml</value>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>                
                <prop key="hibernate.connection.autocommit">true</prop>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.use_sql_comments">true</prop>
                <prop key="hibernate.format_sql">true</prop> 
                <prop key="hibernate.order_inserts">${hibernate.order_inserts}</prop>
                <prop key="hibernate.order_updates">${hibernate.order_updates}</prop>
                <prop key="hibernate.jdbc.batch_size">${hibernate.jdbc.batch_size}</prop>                
            </props>
        </property>
    </bean>


    <bean id="txManagerTest" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory2"/>
    </bean>

    <tx:annotation-driven transaction-manager="txManagerTest"/>

2)User.java实体类

@Entity
@Table(name="Users")
public class User extends BaseObject implements UserDetails, Serializable, Lifecycle{

    private static final long serialVersionUID = -6417085153537327127L;

    private Long userId;    
    private String firstname;    
    private String lastname;    
    private String shortName;    
    private String fullName;    
    private String realName;    
    private String email;
    private String mobile;
    private String password;    
    private String username;        
    private String phone;    
    private String phone2;    
    private String phone3;    
    private String fax;    
    private String sipAccount;
    private Integer status;    
    private Integer workplace;    
    private Integer departmentId;    
    private Integer appType;        
    private boolean accountNonExpired = true;    
    private boolean accountNonLocked = true;    
    private boolean credentialsNonExpired = true;    
    private boolean enabled = true;
    private Set<Role> roles = new HashSet<>();
    private Set<ProjectMember> projectMemberships = new HashSet<>();
    private List<ProfileItem> profileItems = new ArrayList<>();

    public User() {
    }

    /**
     * @return the id
     */
    @Id @GeneratedValue(strategy=GenerationType.AUTO) @Column(name="Users_id")
    public Long getUserId() {
        return userId;
    }

    /**
     * @param id the id to set
     */
    public void setUserId(Long id) {
        this.userId = id;
    }

    /**
     * @return the firstName
     */
    @Column(name="Users_firstname")
    public String getFirstname() {
        return firstname;
    }

    /**
     * @param firstName the firstName to set
     */
    public void setFirstname(String firstname) {
        this.firstname = firstname;
    }

    /**
     * @return the lastName
     */
    @Column(name="Users_lastname")
    public String getLastname() {
        return lastname;
    }

    /**
     * @param lastName the lastName to set
     */
    public void setLastname(String lastname) {
        this.lastname = lastname;
    }

    /**
     * @return the email
     */
    @Column(name="email")
    public String getEmail() {
        return email;
    }

    /**
     * @param email the email to set
     */
    public void setEmail(String email) {
        this.email = email;
    }


    @Override
    @Transient
    public Collection<GrantedAuthority> getAuthorities() {

        Set<GrantedAuthority> ga = new HashSet<>();

        for (Role role : roles) {
            ga.add(new GrantedAuthorityImpl(role.getAuthority()));
        }

        return ga;

    }


    @Override
    @Column(name="password")
    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }


    @Override
    @Column(name="User_name", unique=true)
    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    /**
     * @return the roles
     */
    @ManyToMany(fetch=FetchType.EAGER)
    @JoinTable(name="user_x_role", joinColumns = { @JoinColumn(name="user_id") }, inverseJoinColumns = { @JoinColumn(name="role_id")})    
    public Set<Role> getRoles() {
        return roles;
    }

    /**
     * @param roles the roles to set
     */
    public void setRoles(Set<Role> roles) {
        this.roles = roles;
    }

    public void addRole(Role role) {
        this.getRoles().add(role);
    }

    @Override
    @Transient
    public boolean isAccountNonExpired() {
        return accountNonExpired;
    }

    public void setAccountNonExpired(boolean accountNonExpired) {
        this.accountNonExpired = accountNonExpired;
    }

    @Override
    @Transient
    public boolean isAccountNonLocked() {
        return accountNonLocked;
    }

    public void setAccountNonLocked(boolean accountNonLocked) {
        this.accountNonLocked = accountNonLocked;
    }

    @Override
    @Transient
    public boolean isCredentialsNonExpired() {
        return credentialsNonExpired;
    }

    public void setCredentialsNonExpired(boolean credentialsNonExpired) {
        this.credentialsNonExpired = credentialsNonExpired;
    }

    @Override
    @Transient
    public boolean isEnabled() {
        return enabled;
    }

    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }

    @Override
    public int hashCode() {
        return new HashCodeBuilder(11, 37).append(userId).toHashCode();
    }

    @Override
    public boolean equals(Object o) {
        if (null == o) return false;
        if (!(o instanceof User)) return false;
        if (this == o) return true;

        User input = (User) o;
        return new EqualsBuilder().append(this.getUserId(), input.getUserId()).isEquals();

    }

    @Override
    public String toString() {
        return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE).append(userId).toString();
    }

    /**
     * @return the shortName
     */
    @Column(name="short_name")
    public String getShortName() {
        return shortName;
    }

    /**
     * @param shortName the shortName to set
     */
    public void setShortName(String shortName) {
        this.shortName = shortName;
    }

    /**
     * @return the fullName
     */
    @Column(name="full_name")
    public String getFullName() {
        return fullName;
    }

    /**
     * @param fullName the fullName to set
     */
    public void setFullName(String fullName) {
        this.fullName = fullName;
    }

    /**
     * @return the realName
     */
    @Column(name="real_name")
    public String getRealName() {
        return realName;
    }

    /**
     * @param realName the realName to set
     */
    public void setRealName(String realName) {
        this.realName = realName;
    }

    /**
     * @return the phone
     */
    @Column(name="phone")
    public String getPhone() {
        return phone;
    }

    /**
     * @param phone the phone to set
     */
    public void setPhone(String phone) {
        this.phone = phone;
    }

    /**
     * @return the phone2
     */
    @Column(name="phone2")
    public String getPhone2() {
        return phone2;
    }

    /**
     * @param phone2 the phone2 to set
     */
    public void setPhone2(String phone2) {
        this.phone2 = phone2;
    }

    /**
     * @return the phone3
     */
    @Column(name="phone3")
    public String getPhone3() {
        return phone3;
    }

    /**
     * @param phone3 the phone3 to set
     */
    public void setPhone3(String phone3) {
        this.phone3 = phone3;
    }

    /**
     * @return the fax
     */
    @Column(name="fax")
    public String getFax() {
        return fax;
    }

    /**
     * @param fax the fax to set
     */
    public void setFax(String fax) {
        this.fax = fax;
    }

    /**
     * @return the sipAccount
     */
    @Column(name="sip_account")
    public String getSipAccount() {
        return sipAccount;
    }

    /**
     * @param sipAccount the sipAccount to set
     */
    public void setSipAccount(String sipAccount) {
        this.sipAccount = sipAccount;
    }

    /**
     * @return the status
     */
    @Column(name="users_status")
    public Integer getStatus() {
        return status;
    }

    /**
     * @param status the status to set
     */
    public void setStatus(Integer status) {
        this.status = status;
    }

    /**
     * @return the workplace
     */
    @Column(name="workplace")
    public Integer getWorkplace() {
        return workplace;
    }

    /**
     * @param workplace the workplace to set
     */
    public void setWorkplace(Integer workplace) {
        this.workplace = workplace;
    }

    /**
     * @return the departmentId
     */
    @Column(name="department_id")
    public Integer getDepartmentId() {
        return departmentId;
    }

    /**
     * @param departmentId the departmentId to set
     */
    public void setDepartmentId(Integer departmentId) {
        this.departmentId = departmentId;
    }

    /**
     * @return the profileItems
     */
    @Transient
    public List<ProfileItem> getProfileItems() {
        return profileItems;
    }

    /**
     * @param profileItems the profileItems to set
     */
    public void setProfileItems(List<ProfileItem> profileItems) {
        this.profileItems = profileItems;
    }

    @Override
    public boolean onSave(Session sn) throws CallbackException {
        return false;
    }

    @Override
    public boolean onUpdate(Session sn) throws CallbackException {
        return false;
    }

    @Override
    public boolean onDelete(Session sn) throws CallbackException {
        return false;
    }

    @Override
    public void onLoad(Session sn, Serializable srlzbl) {

        // otevru novou session
        Session session = sn.getSessionFactory().openSession();

        // vytvorim dotaz s ulozenou procedurou        
        SQLQuery query = session.createSQLQuery("SELECT profile_items_id as profileItemId, profile_items_text as profileItemText, profile_items_value as profileItemValue FROM dbo.fnc_user_profile(?)");

        //nastavim userId jako parametr
        query.setInteger(0, this.getUserId().intValue());

        query.setResultTransformer(Transformers.aliasToBean(ProfileItem.class));

        query.addScalar("profileItemId", new LongType() );
        query.addScalar("profileItemText", new StringType());
        query.addScalar("profileItemValue",new StringType());

        // ziskam seznam polozek
        List<ProfileItem> li = query.list();

        // nastavim seznam do objektu
        this.setProfileItems(li);

    }

    /**
     * @return the appType
     */
    @Transient
    public Integer getAppType() {
        return appType;
    }

    /**
     * @param appType the appType to set
     */
    public void setAppType(Integer appType) {
        this.appType = appType;
    }

    /**
     * @return the projectMemberships
     */
    @ManyToMany(fetch=FetchType.EAGER, mappedBy="user")
    public Set<ProjectMember> getProjectMemberships() {
        return projectMemberships;
    }

    /**
     * @param projectMemberships the projectMemberships to set
     */
    public void setProjectMemberships(Set<ProjectMember> projectMemberships) {
        this.projectMemberships = projectMemberships;
    }

    /**
     * @return the mobile
     */
    @Column(name="mobile")
    public String getMobile() {
        return mobile;
    }

    /**
     * @param mobile the mobile to set
     */
    public void setMobile(String mobile) {
        this.mobile = mobile;
    }

}

3) UserDaoImpl 类 - 方法 findByUsername

    @Override
    public User findByUsername(String username) {

        String sSQL;

        sSQL = "select u.* from Users u " +
                "where u.Delete_statute = 0 and u.users_status = 1 " +
                "and u.User_name collate SQL_Latin1_General_Cp1250_CS_AS = :username";

        SQLQuery query = this.getSession(true).createSQLQuery(sSQL);
        query.addEntity(User.class);
        query.setString("username", username);

        List<User> users = query.list();

        User user = null;

        if (users.size() == 1) {
            user = users.get(0);            
        }

        return user;
    }

4)我的许多测试课程之一

@Autowired
private UserDao userDao;

@Before
public void setUp() throws Exception {

  User user = userDao.findByUsername("arnold_foukal");

  SecurityContextHolder.getContext().setAuthentication(                           
        new UsernamePasswordAuthenticationToken(user,"melioidosa")
  );        

}

@Test
public void getEmailTemplateTest() throws Exception {

    System.out.println("-------------------------");
    System.out.println("getEmailTemplate()");
    System.out.println("-------------------------");

    EmailTemplate et = emailDao.getEmailTemplate(82);

    System.out.println(et.getEmailTemplateText());

    System.out.println(et == null);

}

当我运行 getEmailTemplateTest() 时,首先会执行 setUp(),但不幸的是我得到了以下异常:

Testsuite: cz.mbaf.contact.test.EmailServiceTest Hibernate: 
    /* dynamic native SQL query */ select
        u.* 
    from
        Users u 
    where
        u.Delete_statute = 0 
        and u.users_status = 1 
        and u.User_name collate SQL_Latin1_General_Cp1250_CS_AS = ? Tests run: 1, Failures: 0, Errors: 1, Time elapsed: 7,69 sec

------------- Standard Output --------------- Hibernate: 
    /* dynamic native SQL query */ select
        u.* 
    from
        Users u 
    where
        u.Delete_statute = 0 
        and u.users_status = 1 
        and u.User_name collate SQL_Latin1_General_Cp1250_CS_AS = ?
------------- ---------------- --------------- Testcase: getEmailTemplateTest(cz.mbaf.contact.test.EmailServiceTest):   Caused an ERROR could not execute query org.hibernate.exception.GenericJDBCException: could not execute query   at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:140)    at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:128) Test cz.mbaf.contact.test.EmailServiceTest FAILED

感谢帮助!

编辑://这是我的 testdb.script:

SET DATABASE UNIQUE NAME HSQLDB3EEFDE0E4E
SET DATABASE GC 0
SET DATABASE DEFAULT RESULT MEMORY ROWS 0
SET DATABASE EVENT LOG LEVEL 0
SET DATABASE SQL NAMES FALSE
SET DATABASE SQL REGULAR NAMES TRUE
SET DATABASE SQL REFERENCES FALSE
SET DATABASE SQL SIZE TRUE
SET DATABASE SQL TYPES FALSE
SET DATABASE SQL TDC DELETE TRUE
SET DATABASE SQL TDC UPDATE TRUE
SET DATABASE SQL TRANSLATE TTI TYPES TRUE
SET DATABASE SQL CONCAT NULLS TRUE
SET DATABASE SQL NULLS FIRST TRUE
SET DATABASE SQL UNIQUE NULLS TRUE
SET DATABASE SQL CONVERT TRUNCATE TRUE
SET DATABASE SQL AVG SCALE 0
SET DATABASE SQL DOUBLE NAN TRUE
SET DATABASE SQL LONGVAR IS LOB FALSE
SET DATABASE SQL SYNTAX MSS TRUE
SET DATABASE TRANSACTION CONTROL LOCKS
SET DATABASE DEFAULT ISOLATION LEVEL READ COMMITTED
SET DATABASE TRANSACTION ROLLBACK ON CONFLICT TRUE
SET DATABASE TEXT TABLE DEFAULTS ''
SET FILES WRITE DELAY 500 MILLIS
SET FILES BACKUP INCREMENT TRUE
SET FILES CACHE SIZE 10000
SET FILES CACHE ROWS 50000
SET FILES SCALE 32
SET FILES LOB SCALE 32
SET FILES DEFRAG 0
SET FILES NIO TRUE
SET FILES NIO SIZE 256
SET FILES LOG TRUE
SET FILES LOG SIZE 50
CREATE USER SA PASSWORD DIGEST 'd41d8cd98f00b204e9800998ecf8427e'
ALTER USER SA SET LOCAL TRUE
CREATE SCHEMA PUBLIC AUTHORIZATION DBA
CREATE SCHEMA DBA AUTHORIZATION SA
CREATE COLLATION DBA.SQL_LATIN1_GENERAL_CP1250_CS_AS FOR INFORMATION_SCHEMA.SQL_TEXT FROM SQL_TEXT PAD SPACE
SET SCHEMA DBA
CREATE MEMORY TABLE DBA.USERS(USERS_ID INTEGER PRIMARY KEY,USER_NAME VARCHAR(16777216),USERS_TYP VARCHAR(16777216),FULL_NAME VARCHAR(16777216),SHORT_NAME VARCHAR(16777216),USERS_FIRSTNAME VARCHAR(16777216),USERS_LASTNAME VARCHAR(16777216),USERS_INIT VARCHAR(10),DEPARTMENT VARCHAR(16777216),PERSON_DESCRIPTION VARCHAR(16777216),REAL_NAME VARCHAR(16777216),PHONE VARCHAR(50),PHONE2 VARCHAR(50),PHONE3 VARCHAR(50),GROUP_PHONE VARCHAR(16777216),LINE VARCHAR(3),GROUP_LINE VARCHAR(3),SWITCHBOARD_STATUTE_ID TINYINT,SWITCHBOARD_LINE SMALLINT,SWITCHBOARD_LAST_ACTION TIMESTAMP,FAX VARCHAR(50),MOBILE VARCHAR(50),EMAIL VARCHAR(500),OPERATOR_GROUP_ID VARCHAR(3),DEPARTMENT_ID INTEGER,PRIMARY_GROUP_USER INTEGER NOT NULL,WORKPLACE INTEGER,USERS_STATUS INTEGER,USERS_END_DATE TIMESTAMP,SIP_ACCOUNT VARCHAR(50),SKYPE_ACCOUNT VARCHAR(50),INSERT_USER VARCHAR(16777216) NOT NULL,INSERT_DATE TIMESTAMP NOT NULL,UPDATE_USER VARCHAR(16777216),UPDATE_DATE TIMESTAMP,DELETE_USER VARCHAR(16777216),DELETE_DATE TIMESTAMP,DELETE_STATUTE INTEGER NOT NULL,UPDATE_DATE_DBO TIMESTAMP,USER_ALIAS VARCHAR(50),WEB_PASSWORD VARBINARY(256),SOUD_CTU INTEGER,LANGUAGE INTEGER NOT NULL,PASSWORD VARCHAR(50),ACCOUNT_EXPIRED BIT(1) NOT NULL,ACCOUNT_LOCKED BIT(1) NOT NULL,CREDENTIALS_EXPIRED BIT(1) NOT NULL,ACCOUNT_ENABLED BIT(1) NOT NULL,TEAMLEADER INTEGER,IP_ADDRESS VARCHAR(16777216) NOT NULL)
ALTER SEQUENCE SYSTEM_LOBS.LOB_ID RESTART WITH 1
SET DATABASE DEFAULT INITIAL SCHEMA DBA
GRANT USAGE ON DOMAIN INFORMATION_SCHEMA.YES_OR_NO TO PUBLIC
GRANT USAGE ON DOMAIN INFORMATION_SCHEMA.TIME_STAMP TO PUBLIC
GRANT USAGE ON DOMAIN INFORMATION_SCHEMA.CARDINAL_NUMBER TO PUBLIC
GRANT USAGE ON DOMAIN INFORMATION_SCHEMA.CHARACTER_DATA TO PUBLIC
GRANT USAGE ON DOMAIN INFORMATION_SCHEMA.SQL_IDENTIFIER TO PUBLIC
GRANT DBA TO SA
SET SCHEMA SYSTEM_LOBS
INSERT INTO BLOCKS VALUES(0,2147483647,0)
SET SCHEMA DBA
INSERT INTO USERS VALUES(1,'arnold_foukal',NULL,'Arnold Foukal','A. Foukal','Arnold','Foukal','AF','Department 1',NULL,'Arnold Foukal','777888111','777888112','777888113',NULL,NULL,NULL,NULL,NULL,NULL,'777888114',NULL,'foukal@mbaf.cz','20',1,0,1,1,NULL,'012',NULL,'jony','2010-07-01 11:07:47.370000','jony','2011-02-25 11:42:34.110000',NULL,NULL,0,NULL,NULL,NULL,NULL,1,'79ce95c4d1e7524f969b9fced078f67e47dc394f','0','0','0','1',NULL,'Dynamic')
4

2 回答 2

0

您的查询引用特定于 MS SQL Server 的特定排序规则。在 HSQLDB 下运行时,您不能使用此排序规则,除非您事先在数据库中创建它。

CREATE COLLATION SQL_Latin1_General_Cp1250_CS_AS FOR INFORMATION_SCHEMA.SQL_TEXT 
    FROM INFORMATION_SCHEMA.SQL_TEXT PAD SPACE
于 2013-05-30T10:07:25.037 回答
0

HSQLDB 语法不允许在 WHERE 子句中使用 COLLATE。这是一个更大的问题,除了 MS SQL Server 特定的 COLLATION 类型。

我正在为此寻找解决方案,因为我有同样的问题(产品中的 MS SQL 和 HSQLDB 作为潜在的内存数据库进行测试)。

于 2015-05-08T18:36:48.107 回答